使用多个角色授权属性

我想将授权添加到控制器中,一次用于多个角色。

通常情况下是这样的:

[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}

但是我已经将角色存储在 const 中,因为它们可能会在某个时候更改或扩展。

public const RoleA = "RoleA";
public const RoleB = "RoleB";
public const RoleC = "RoleC";

我不能这样做,因为必须在编译时知道字符串:

[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}

有办法避开这个问题吗?

我可以写一个常数,其中只包含“角色 A,角色 B,角色 C”-但我不喜欢魔术字符串,这是一个魔术字符串。更改“角色”的名称并忘记更改组合字符串将是一场灾难。

我使用的是 MVC5.ASP.NET 标识和编译时已知的角色。

99589 次浏览

Try to create custom authorize attribute like this.

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
public AuthorizeRolesAttribute(params string[] roles) : base()
{
Roles = string.Join(",", roles);
}
}

Assuming your roles will be the same for multiple controllers, create a helper class:

public static class Role
{
public const string Administrator = "Administrator";
public const string Assistant = "Assistant";
}

Then use it like so:

public class MyController : Controller
{
[AuthorizeRoles(Role.Administrator, Role.Assistant)]
public ActionResult AdminOrAssistant()
{
return View();
}
}

Make sure you are deriving your custom attribute class off System.Web.Mvc.AuthorizeAttribute and NOT System.Web.Http.AuthorizeAttribute.

I ran into the same problem. Once I changed it, everything worked.

You may also want to add the following to your custom attribute class:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]

The best and simplest way I found to resolve this problem is just to concatenate roles in the Authorize attribute.

[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]

with CustomRole a class with constant strings like this :

public static class CustomRoles
{
public const string Admin = "Admin";
// and so on..
}

I feel like a custom authorize attribute is overkill for this issue unless you have a large amount of roles.

Since the string must be known at compile time, why not make a static Role class that contains public strings of the roles you have defined, and then add comma separated strings with certain roles that you want to authorize:

public static class Roles
{
public const string ADMIN = "Admin";
public const string VIEWER = "Viewer";


public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER;
}

And then you can use the Authorize Attribute like so on the Controller Class or the Controller Method (or both):

[Authorize(Roles = Roles.ADMIN]
public class ExampleController : Controller
{
[Authorize(Roles = Roles.ADMIN_OR_VIEWER)
public ActionResult Create()
{
..code here...
}
}

What i did is the answer in @Tieson

I tweak a little in his answer. Instead of string.Join why not convert it to list?

Here is my answer:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
private new List<string> Roles;
public AuthorizeRolesAttribute(params string[] roles) : base()
{
Roles = roles.toList()
}
}

And then check the if the role is valid overriding OnAuthorization

public override void OnAuthorization(HttpActionContext actionContext)
{
if (Roles == null)
HandleUnauthorizedRequest(actionContext);
else
{
ClaimsIdentity claimsIdentity = HttpContext.Current.User.Identity as ClaimsIdentity;
string _role = claimsIdentity.FindFirst(ClaimTypes.Role).Value;
bool isAuthorize = Roles.Any(role => role == _role);


if(!isAuthorize)
HandleUnauthorizedRequest(actionContext);
}
}

And there you have it, it is now validating if the role is authorized to access the resource