多角色授权属性
本文关键字:属性 授权 角色 | 更新日期: 2023-09-27 18:08:13
我想为控制器添加授权,同时为多个角色。
通常是这样的:
[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()
{
}
有没有办法规避这个问题?
我可以写一个仅仅包含"RoleA,RoleB,RoleC"的const -但是我不喜欢神奇的字符串,这就是一个神奇的字符串。更改角色的名称而忘记更改组合字符串将是一场灾难。
我正在使用MVC5。ASP。. NET身份和角色在编译时是已知的。
尝试创建这样的自定义授权属性。
public class AuthorizeRolesAttribute : AuthorizeAttribute
{
public AuthorizeRolesAttribute(params string[] roles) : base()
{
Roles = string.Join(",", roles);
}
}
假设你的角色对于多个控制器是相同的,创建一个helper类:
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();
}
}
我发现解决这个问题的最好和最简单的方法就是在Authorize属性中连接角色。
[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]
与CustomRole类的常量字符串如下:
public static class CustomRoles
{
public const string Admin = "Admin";
// and so on..
}
确保您的自定义属性类是基于System.Web.Mvc.AuthorizeAttribute
而不是System.Web.Http.AuthorizeAttribute
。
我遇到了同样的问题。一旦我改变了它,一切都正常了。
您可能还想在自定义属性类中添加以下内容:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
我所做的就是@Tieson的答案
我对他的回答略加修改。而不是字符串。Join为什么不转换成list呢?我的答案是:
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);
}
}
现在验证角色是否被授权访问资源
我觉得自定义授权属性对于这个问题来说是多余的,除非您有大量的角色。
既然字符串必须在编译时已知,为什么不创建一个静态Role类,其中包含您已定义的角色的公共字符串,然后在您想要授权的某些角色中添加逗号分隔的字符串:
public static class Roles
{
public const string ADMIN = "Admin";
public const string VIEWER = "Viewer";
public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER;
}
然后你可以像这样在控制器类或控制器方法(或两者)上使用授权属性:
[Authorize(Roles = Roles.ADMIN]
public class ExampleController : Controller
{
[Authorize(Roles = Roles.ADMIN_OR_VIEWER)
public ActionResult Create()
{
..code here...
}
}