How do you create a custom AuthorizeAttribute in ASP.NET Core?

前端 未结 11 1206
春和景丽
春和景丽 2020-11-21 17:19

I\'m trying to make a custom authorization attribute in ASP.NET Core. In previous versions it was possible to override bool AuthorizeCore(HttpContextBase httpContext)

11条回答
  •  一向
    一向 (楼主)
    2020-11-21 17:50

    You can create your own AuthorizationHandler that will find custom attributes on your Controllers and Actions, and pass them to the HandleRequirementAsync method.

    public abstract class AttributeAuthorizationHandler : AuthorizationHandler where TRequirement : IAuthorizationRequirement where TAttribute : Attribute
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement)
        {
            var attributes = new List();
    
            var action = (context.Resource as AuthorizationFilterContext)?.ActionDescriptor as ControllerActionDescriptor;
            if (action != null)
            {
                attributes.AddRange(GetAttributes(action.ControllerTypeInfo.UnderlyingSystemType));
                attributes.AddRange(GetAttributes(action.MethodInfo));
            }
    
            return HandleRequirementAsync(context, requirement, attributes);
        }
    
        protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement, IEnumerable attributes);
    
        private static IEnumerable GetAttributes(MemberInfo memberInfo)
        {
            return memberInfo.GetCustomAttributes(typeof(TAttribute), false).Cast();
        }
    }
    

    Then you can use it for any custom attributes you need on your controllers or actions. For example to add permission requirements. Just create your custom attribute.

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    public class PermissionAttribute : AuthorizeAttribute
    {
        public string Name { get; }
    
        public PermissionAttribute(string name) : base("Permission")
        {
            Name = name;
        }
    }
    

    Then create a Requirement to add to your Policy

    public class PermissionAuthorizationRequirement : IAuthorizationRequirement
    {
        //Add any custom requirement properties if you have them
    }
    

    Then create the AuthorizationHandler for your custom attribute, inheriting the AttributeAuthorizationHandler that we created earlier. It will be passed an IEnumerable for all your custom attributes in the HandleRequirementsAsync method, accumulated from your Controller and Action.

    public class PermissionAuthorizationHandler : AttributeAuthorizationHandler
    {
        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement, IEnumerable attributes)
        {
            foreach (var permissionAttribute in attributes)
            {
                if (!await AuthorizeAsync(context.User, permissionAttribute.Name))
                {
                    return;
                }
            }
    
            context.Succeed(requirement);
        }
    
        private Task AuthorizeAsync(ClaimsPrincipal user, string permission)
        {
            //Implement your custom user permission logic here
        }
    }
    

    And finally, in your Startup.cs ConfigureServices method, add your custom AuthorizationHandler to the services, and add your Policy.

            services.AddSingleton();
    
            services.AddAuthorization(options =>
            {
                options.AddPolicy("Permission", policyBuilder =>
                {
                    policyBuilder.Requirements.Add(new PermissionAuthorizationRequirement());
                });
            });
    

    Now you can simply decorate your Controllers and Actions with your custom attribute.

    [Permission("AccessCustomers")]
    public class CustomersController
    {
        [Permission("AddCustomer")]
        IActionResult AddCustomer([FromBody] Customer customer)
        {
            //Add customer
        }
    }
    

提交回复
热议问题