我想将Authorization添加到控制器,同时为多个角色添加。
通常情况如下:
[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}
但是我已将我的角色存储在角落中,因为它们可能会在某些时候改变或扩展。
public const RoleA = "RoleA";
public const RoleB = "RoleB";
public const RoleC = "RoleC";
我不能这样做,因为字符串必须在编译时知道:
[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}
有没有办法规避这个问题?
我可以编写一个只包含“RoleA,RoleB,RoleC”的const - 但我不喜欢魔术字符串,这是一个神奇的字符串。更改角色名称而忘记更改组合字符串将是一场灾难。
我正在使用MVC5。 ASP.NET Identity和Role在编译时是已知的。
答案 0 :(得分:159)
尝试创建自定义授权属性,例如this。
public class AuthorizeRolesAttribute : AuthorizeAttribute
{
public AuthorizeRolesAttribute(params string[] roles) : base()
{
Roles = string.Join(",", roles);
}
}
假设您的角色对于多个控制器是相同的,请创建一个帮助类:
public static class Role
{
public const string Administrator = "Administrator";
public const string Assistant = "Assistant";
}
然后像这样使用它:
public class MyController : Controller
{
[AuthorizeRoles(Role.Administrator, Role.Assistant)]
public ActionResult AdminOrAssistant()
{
return View();
}
}
答案 1 :(得分:8)
确保您从System.Web.Mvc.AuthorizeAttribute
而不是System.Web.Http.AuthorizeAttribute
派生自定义属性类。
我遇到了同样的问题。一旦我改变它,一切都有效。
您可能还想将以下内容添加到自定义属性类中:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
答案 2 :(得分:7)
我发现解决此问题的最佳和最简单的方法就是在Authorize属性中连接角色。
[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]
使用CustomRole一个具有常量字符串的类:
public static class CustomRoles
{
public const string Admin = "Admin";
// and so on..
}
答案 3 :(得分:3)
我所做的就是@Tieson的答案
我在他的回答中略微调整一下。而不是string.Join为什么不将它转换为列表?
以下是我的回答:
public class AuthorizeRolesAttribute : AuthorizeAttribute
{
private new List<string> Roles;
public AuthorizeRolesAttribute(params string[] roles) : base()
{
Roles = roles.toList()
}
}
然后检查角色是否有效覆盖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);
}
}
如果你拥有它,它现在正在验证角色是否有权访问资源
答案 4 :(得分:0)
除非你有大量的角色,否则我觉得自定义授权属性对此问题来说是过度的。
由于字符串必须在编译时知道,为什么不创建一个包含已定义角色的公共字符串的静态Role类,然后添加逗号分隔的字符串以及您要授权的某些角色:
public static class Roles
{
public const string ADMIN = "Admin";
public const string VIEWER = "Viewer";
public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER;
}
然后您可以在Controller类或Controller方法(或两者)上使用Authorize Attribute:
[Authorize(Roles = Roles.ADMIN]
public class ExampleController : Controller
{
[Authorize(Roles = Roles.ADMIN_OR_VIEWER)
public ActionResult Create()
{
..code here...
}
}