Authorize Attribute with Multiple Roles

﹥>﹥吖頭↗ 提交于 2019-11-28 03:17:49
MacGyver

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();
    }
}
Jerry Finegan

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)] 
ChristopheHvd

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..
}

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

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...
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!