Overriding controller AuthorizeAttribute for just one action

前端 未结 4 1550
谎友^
谎友^ 2020-12-01 08:35

I have a controller decorated with an AuthorizeAttribute. The controller contains several actions that all require authentication apart from one action that requires some cu

相关标签:
4条回答
  • 2020-12-01 09:18

    After way too much time, I came up with a solution. You need to decorate your controller with a custom AuthorizeAttribute.

    public class OverridableAuthorize : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var action = filterContext.ActionDescriptor;
            if(action.IsDefined(typeof(IgnoreAuthorization), true)) return;
    
            var controller = action.ControllerDescriptor;
            if(controller.IsDefined(typeof(IgnoreAuthorization), true)) return;
    
            base.OnAuthorization(filterContext);
        }
    }
    

    Which can be paired with AllowAnonymous on an Action

    [AllowAnonymous]
    
    0 讨论(0)
  • 2020-12-01 09:24

    All you need to override the [Authorize] from the controller, for a specific action is to add

    [AllowAnonymous] 
    

    to the action you want to not be authorized (then add your custom attribute as required).

    See the comments / intellisense :

    Represents an attribute that marks controllers and actions to skip the System.Web.Mvc.AuthorizeAttribute during authorization.

    0 讨论(0)
  • 2020-12-01 09:35

    In MVC 5 you can override the authorization for any action using the new attribute OverrideAuthorization. Basically, you add it to an action that has a different authorization configuration than the one defined in the controller.

    You do it like this:

    [OverrideAuthorization]
    [Authorize(Roles = "Employee")]
    public ActionResult List() { ... }
    

    More information at http://www.c-sharpcorner.com/UploadFile/ff2f08/filter-overrides-in-Asp-Net-mvc-5/

    In ASP.NET Core 2.1 there's no OverrideAuthorization attribute and the only thing you can do is make an action anonymous, even if the controller is not. More information at https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.1

    One option is to do it this way:

    [Authorize(Roles = "Admin,Employee")] // admin or employee
    public class XController : Controller 
    {
        [Authorize(Roles = "Admin")] // only admin
        public ActionResult ActionX() { ... }
    
        [AllowAnonymous] // anyone
        public ActionResult ActionX() { ... }
    }
    
    0 讨论(0)
  • 2020-12-01 09:41

    You can change the Order in which the attributes run (using the Order property), but I believe that in this case they will still both run unless one generates a result with immediate effect. The key is to have the least restrictive attribute applied at the highest level (class) and get more restrictive for the methods. If you wanted the Home action to be publicly available, for instance, you would need to remove the Authorize attribute from the class, and apply it to each of the other methods.

    If the action has the same level of permissiveness, but has a different result, changing the order may be sufficient. For example, you would normally redirect to the Logon action, but for Home you want to redirect to the About action. In this, case give the class attribute Order=2 and the Home action attribute Order=1.

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