Allow multiple roles to access controller action

前端 未结 9 1186
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-29 15:19

Right now I decorate a method like this to allow \"members\" to access my controller action

[Authorize(Roles=\"members\")]

How do I

相关标签:
9条回答
  • 2020-11-29 15:41

    For MVC4, using a Enum (UserRoles) with my roles, I use a custom AuthorizeAttribute.

    On my controlled action, I do:

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

    And I use a custom AuthorizeAttribute like that:

    [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;
            }
        }
    }
    

    This is part of modifed FNHMVC by Fabricio Martínez Tamayo https://github.com/fabriciomrtnz/FNHMVC/

    0 讨论(0)
  • 2020-11-29 15:46

    Better code with adding a subclass 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 }
                      }
                  );
                }
            }
        }
    

    How to use this

    [AuthorizeRole(Rolenames.Admin,Rolenames.Member)]
    
    public ActionResult Index()
    {
    return View();
    }
    
    0 讨论(0)
  • 2020-11-29 15:53

    One possible simplification would be to subclass AuthorizeAttribute:

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

    Usage:

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

    Semantically it is the same as Jim Schmehil's answer.

    0 讨论(0)
提交回复
热议问题