多角色授权属性

本文关键字:属性 授权 角色 | 更新日期: 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...
    }
}