Dependency Injection on AuthorizationOptions Requirement in DotNet Core

前端 未结 2 1321
萌比男神i
萌比男神i 2021-02-04 11:37

I have a .NET core project and am trying to create a custom policy using AuthorizationOptions as shown in the documentation located here:

ASP.NET.Core Authorization - De

2条回答
  •  我在风中等你
    2021-02-04 12:07

    OK, I'm going to make an assumption here, and that is that you need to inject an instance of MyDbContext in UserNameRequirement to perform the business logic.

    If this is the case, then it means UserNameRequirement both holds the data - in your case the username - and does the authorization logic. An example of this in ASP.NET Core is the ClaimsAuthorizationRequirement.

    The solution to this is to separate this into two classes - on one side the requirement that just holds the data associated with the requirement, on on the other side the authorization handler. As a note, even if we'll go through it, what I'm describing is available in the official ASP.NET Core docs.

    So the requirement class could look something like:

    public class UserNameRequirement : IAuthorizationRequirement
    {
        public class UserNameRequirement(string userName)
        {
            UserName = userName;
        }
    
        public string UserName { get; }
    }
    

    and the handler class would be:

    public class UserNameRequirementHandler : AuthorizationHandler
    {
        private readonly MyDbContext _dbContext;
    
        public UserNameRequirementHandler(MyDbContext dbContext)
        {
            _dbContext = dbContext;
        }
    
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserNameRequirement requirement)
        {
            var userName = requirement.UserName;
    
            // Use _dbContext to perform business logic
        }
    }
    

    The next and last part is to register the handler in the container:

    services.AddSingleton();
    

    The effect of doing this is that you can now add your requirement to the policy without worrying about the DbContext:

    services.AddAuthorization(options =>
    {
        options.AddPolicy(
            "UserNamePolicy",
            policy => policy.Requirements.Add(new UserNameRequirement("admin")));
    }
    

    Internally, ASP.NET will then resolve all the handlers associated with that requirement through the container, so the instance of MyDbContext will be available to you in the handler, allowing you to perform the business logic as you see fit.

    Hopefully, my assumption is correct, and this helps you.

    Edit:

    Henry Roux made a good point in a comment below regarding the fact that if the UserNameRequirementHandler is registered as a singleton, then a single instance of MyDbContext will be used, and that could lead to issues. Make sure you register your authorization handlers with the appropriate lifecycle.

提交回复
热议问题