允许多个角色访问控制器操作


274

现在,我装饰这样的方法,以允许“成员”访问我的控制器操作

[Authorize(Roles="members")]

如何允许多个角色?例如,以下内容不起作用,但它显示了我要执行的操作(允许“成员”和“管理员”访问):

[Authorize(Roles="members", "admin")] 

4
请更改此问题的可接受答案。具有当前接受答案的人对其进行了编辑,表明他错了。
Eric J.

Answers:


595

另一种选择是在发布时使用单个授权过滤器,但删除内部引号。

[Authorize(Roles="members,admin")]

5
也可以在MVC 5中使用。+1
gkonuralp 2015年

4
适用于ASP.NET Core 1.0(MVC 6)和Microsoft.AspNet.Identity v3。*
Soren

3
如果您只有一个需要授权的控制器,则可以。如果您有多个,则您要复制这些字符串常量(糟糕)。我更喜欢具有角色名称的静态类。我的宠物讨厌是重复的弦...太糟糕了。
罗宾尼克'18

1
@kraeg好消息,您解决了您的问题。现在,考虑删除您的意见,请
巴勃罗·克劳斯

1
为什么?我花了很长时间才解决这个问题。这对于其他遇到相同问题的人可能会有所帮助。
克拉格

129

如果要使用自定义角色,可以执行以下操作:

CustomRoles 类:

public static class CustomRoles
{
    public const string Administrator = "Administrador";
    public const string User = "Usuario";
}

用法

[Authorize(Roles = CustomRoles.Administrator +","+ CustomRoles.User)]

如果您的角色很少,也许可以将它们组合在一起(为清楚起见),如下所示:

public static class CustomRoles
{
     public const string Administrator = "Administrador";
     public const string User = "Usuario";
     public const string AdministratorOrUser = Administrator + "," + User;  
}

用法

[Authorize(Roles = CustomRoles.AdministratorOrUser)]

7
如果您向不知道CustomRoles背后原因的人进行了解释,这将是一个很好的答案。
James Skemp 2012年

1
@JamesSkemp好的,我已经回答了。这很简单。CustumRoles是我创建的一个类,其中包含一些与我的应用程序角色相对应的常量。我这样做的原因有几个:1)允许使用智能感知以避免拼写错误2)简化维护。如果角色更改,我只需要在应用程序中更新一个位置。
巴勃罗·克劳斯

@Pabloker或者,您可以创建一个带有Flags属性的枚举,例如Convert.ToString(CustomRoles.Administrator | CustomRoles.User); -令人讨厌的部分是,这需要显式转换
cstruter 2012年

如果您有39个角色?
Kiquenet '18

我认为您的问题超出了.net可以完成的许可证建模范围
Pablo Claus

82

一种可能的简化方法是将其子类化AuthorizeAttribute

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

用法:

[Roles("members", "admin")]

从语义上讲,它与吉姆·施密希尔(Jim Schmehil)的答案相同。


3
这对我不起作用,即使用户没有任何角色,登录的用户也可以绕过该属性。
Urielzen

9
当您使用常量作为值时,此答案更好:即[Roles(Constants.Admin,Constants.Owner)]
dalcam

3
这是最好的答案
IgorShch

18

对于MVC4,请在角色中使用EnumUserRoles),然后使用custom AuthorizeAttribute

根据我的控制动作,我会执行以下操作:

[CustomAuthorize(UserRoles.Admin, UserRoles.User)]
public ActionResult ChangePassword()
{
    return View();
}

我使用这样的自定义AuthorizeAttribute

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorize : AuthorizeAttribute
{
    private string[] UserProfilesRequired { get; set; }

    public CustomAuthorize(params object[] userProfilesRequired)
    {
        if (userProfilesRequired.Any(p => p.GetType().BaseType != typeof(Enum)))
            throw new ArgumentException("userProfilesRequired");

        this.UserProfilesRequired = userProfilesRequired.Select(p => Enum.GetName(p.GetType(), p)).ToArray();
    }

    public override void OnAuthorization(AuthorizationContext context)
    {
        bool authorized = false;

        foreach (var role in this.UserProfilesRequired)
            if (HttpContext.Current.User.IsInRole(role))
            {
                authorized = true;
                break;
            }

        if (!authorized)
        {
            var url = new UrlHelper(context.RequestContext);
            var logonUrl = url.Action("Http", "Error", new { Id = 401, Area = "" });
            context.Result = new RedirectResult(logonUrl);

            return;
        }
    }
}

这是FabricioMartínezTamayo修改后的FNHMVC的一部分https://github.com/fabriciomrtnz/FNHMVC/


1
您的OnAuthorization方法将要求用户具有所有枚举的角色;那是故意的,还是您错过了那个循环的中断?
Tieson T.

@Tieson:我仔细检查了一下,似乎肯定需要在该循环中休息一下。
OcelotXL

@TiesonT。@madrush,感谢您的修复,它确实可能在循环中有所中断。我将更改上面的代码。
2015年

枚举UserRoles很好。您是手动声明它还是根据数据库的内容自动生成它?
Konrad Viltersten'1

@KonradViltersten这是手动操作,但我想可以使用反射和自动生成的动态类完成
Bernardo Loureiro,2016年

3

另一个明确的解决方案是,您可以使用常量来保持约定并添加多个[Authorize]属性。看一下这个:

public static class RolesConvention
{
    public const string Administrator = "Administrator";
    public const string Guest = "Guest";
}

然后在控制器中:

[Authorize(Roles = RolesConvention.Administrator )]
[Authorize(Roles = RolesConvention.Guest)]
[Produces("application/json")]
[Route("api/[controller]")]
public class MyController : Controller

14
多个Authorize属性采用AND语义,并且需要满足所有条件(即,用户必须同时具有管理员和来宾角色)。
trousyt

3

如果您发现自己经常使用这两个角色,则可以将它们包装在自己的“授权”中。这实际上是已接受答案的扩展。

using System.Web.Mvc;

public class AuthorizeAdminOrMember : AuthorizeAttribute
{
    public AuthorizeAdminOrMember()
    {
        Roles = "members, admin";
    }
}

然后将您的新授权应用于该操作。我认为这看起来更干净并且易于阅读。

public class MyController : Controller
{
    [AuthorizeAdminOrMember]
    public ActionResult MyAction()
    {
        return null;
    }
}

1

添加子类更好的代码 AuthorizeRole.cs

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
    class AuthorizeRoleAttribute : AuthorizeAttribute
    {
        public AuthorizeRoleAttribute(params Rolenames[] roles)
        {
            this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r)));
        }
        protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {
                filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary {
                  { "action", "Unauthorized" },
                  { "controller", "Home" },
                  { "area", "" }
                  }
              );
                //base.HandleUnauthorizedRequest(filterContext);
            }
            else
            {
                filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary {
                  { "action", "Login" },
                  { "controller", "Account" },
                  { "area", "" },
                  { "returnUrl", HttpContext.Current.Request.Url }
                  }
              );
            }
        }
    }

如何使用

[AuthorizeRole(Rolenames.Admin,Rolenames.Member)]

public ActionResult Index()
{
return View();
}

1

使用AspNetCore 2.x,您必须走一些不同的方式:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class AuthorizeRoleAttribute : AuthorizeAttribute
{
    public AuthorizeRoleAttribute(params YourEnum[] roles)
    {
        Policy = string.Join(",", roles.Select(r => r.GetDescription()));
    }
}

像这样使用它:

[Authorize(YourEnum.Role1, YourEnum.Role2)]

-2
Intent promptInstall = new Intent(android.content.Intent.ACTION_VIEW);
promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
promptInstall.setDataAndType(Uri.parse("http://10.0.2.2:8081/MyAPPStore/apk/Teflouki.apk"), "application/vnd.android.package-archive" );

startActivity(promptInstall);

1
包含代码的答案应至少具有一个简短的描述,以说明代码的工作方式以及其回答问题的原因。进一步的模式,代码段格式需要改进。
罗伯特·卡波尼

??@Orsit Moel,看起来像是复制粘贴到了错误的线程中……
Cameron Forward
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.