【问题标题】:Allow multiple roles to access controller action允许多个角色访问控制器操作
【发布时间】:2010-10-16 13:20:54
【问题描述】:

现在我装饰了一个这样的方法来允许“成员”访问我的控制器操作

[Authorize(Roles="members")]

我如何允许多个角色?例如以下内容不起作用,但它显示了我正在尝试做的事情(允许“成员”和“管理员”访问):

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

【问题讨论】:

  • 请更改此问题的已接受答案。当前接受答案的人对其进行了编辑,表明他错了。

标签: asp.net-mvc controller roles


【解决方案1】:

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

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

【讨论】:

  • 也适用于 MVC 5。 +1
  • 适用于 ASP.NET Core 1.0 (MVC 6) 和 Microsoft.AspNet.Identity v3.*
  • 如果您只有一个需要授权的控制器,这没关系。如果你有多个,你就是在复制那些字符串常量(恶心)。我更喜欢具有角色名称的静态类。我最讨厌重复的字符串……太糟糕了。
  • @kraeg 好消息,您解决了问题。现在,请考虑删除您的 cmets,请
  • 为什么?我花了很长时间才解决这个问题。它可能对遇到相同问题的其他人有所帮助。
【解决方案2】:

如果你想使用自定义角色,你可以这样做:

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

【讨论】:

  • 如果您向不知道 CustomRoles 背后的人解释,这将是一个很好的答案。
  • @JamesSkemp 好的,我已经扩展了我的答案。这很简单。 CustumRoles 是我创建的一个类,其中包含一些常量,与我的应用程序角色相对应。我这样做有几个原因:1)它允许使用智能感知来避免拼写错误 2)简化维护。如果角色发生变化,我只需要更新我的应用程序中的一个地方。
  • @Pabloker 或者,您可以创建一个带有 Flags 属性的枚举,例如Convert.ToString(CustomRoles.Administrator | CustomRoles.User); - 烦人的部分是这需要显式转换
  • 如果你有 39 个角色?
  • 我认为您的问题是通过许可建模超出了 .net 所能完成的范围
【解决方案3】:

对于 MVC4,使用 Enum (UserRoles) 和我的角色,我使用自定义 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;
        }
    }
}

这是 Fabricio Martínez Tamayo https://github.com/fabriciomrtnz/FNHMVC/ 修改的 FNHMVC 的一部分

【讨论】:

  • 您的 OnAuthorization 方法将要求用户拥有所有枚举角色;这是故意的,还是你错过了那个循环的中断?
  • @Tieson:我仔细检查过了,在那个循环中肯定需要休息一下。
  • @TiesonT。和@madrush,我很欣赏你的修复,它真的可以在循环内中断。我把上面的代码改一下。
  • 枚举 UserRoles 很好。是手动声明还是根据数据库内容自动生成?
  • @KonradViltersten 这是手动的,但我猜可以使用反射和动态类自动生成
【解决方案4】:

一种可能的简化是继承AuthorizeAttribute

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

用法:

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

语义上与 Jim Schmehil 的回答相同。

【讨论】:

  • 这对我不起作用,即使用户没有任何角色,登录用户也能够绕过该属性。
  • 当您使用常量作为值时,此答案会更好:即 [Roles(Constants.Admin,Constants.Owner)]
  • 这是最好的答案
  • 我知道这是一篇旧帖子,但让我补充一下。为了让这个代码 sn-p 工作,你必须使用 System.Web.Mvc.AuthorizeAttribute 来处理 System.Web.Mvc.ControllersSystem.Web.Http.AuthorizeAttribute 来处理 System.Web.Http.ApiController(RESTful 调用)。
【解决方案5】:

通过添加子类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();
}

【讨论】:

    【解决方案6】:

    另一个明确的解决方案,您可以使用常量来保持约定并添加多个 [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
    

    【讨论】:

    • 多个 Authorize 属性采用 AND 语义并要求满足所有条件(即用户必须同时具有管理员和访客角色)。
    【解决方案7】:

    如果您发现自己经常应用这 2 个角色,则可以将它们包装在各自的 Authorize 中。这实际上是已接受答案的扩展。

    using System.Web.Mvc;
    
    public class AuthorizeAdminOrMember : AuthorizeAttribute
    {
        public AuthorizeAdminOrMember()
        {
            Roles = "members, admin";
        }
    }
    

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

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

    【讨论】:

      【解决方案8】:

      使用 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)]
      

      【讨论】:

      • Policy = Roles = ?
      • Roles = string.Join(",", roles.Select(r => r.ToString()));
      【解决方案9】:
      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);
      

      【讨论】:

      • 包括代码在内的答案至少应该有一个最低限度的描述,解释代码是如何工作的以及它为什么回答问题。此外,代码段格式需要改进。
      • 嗯? @Orsit Moel,看起来像是复制粘贴到了错误的线程中......
      【解决方案10】:

      您可以使用授权策略 在 Startup.cs 中

          services.AddAuthorization(options =>
          {
              options.AddPolicy("admin", policy => policy.RequireRole("SuperAdmin","Admin"));
              options.AddPolicy("teacher", policy => policy.RequireRole("SuperAdmin", "Admin", "Teacher"));
          });
      

      在控制器文件中:

       [Authorize(Policy = "teacher")]
       [HttpGet("stats/{id}")]
       public async Task<IActionResult> getStudentStats(int id)
       { ... }
      

      “教师”政策接受 3 个角色。

      【讨论】:

        猜你喜欢
        • 2021-11-21
        • 1970-01-01
        • 2020-02-16
        • 1970-01-01
        • 2013-02-05
        • 2016-03-27
        • 2013-12-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多