ASP.NET Core Identity Authorization using Parameter for Team Membership

前端 未结 3 644
长发绾君心
长发绾君心 2021-02-03 13:07

I have an application with tables like this:

  • User (ASP.NET Core Identity)
  • Team
  • UserTeam (many-to-many join table)

Users can be mem

3条回答
  •  孤城傲影
    2021-02-03 13:48

    ASP.NET Core introduces the concept of policies that you can apply to your Authorize attribute. works like filters, but without writing filters.

    Each policy has one or more requirements that must all be met for the policy to pass. The Microsoft docs have a good example of setting up policies. In your case I'd do something like the following:

    First, start with a "requirement"

    public class TeamAccessRequirement : IAuthorizationRequirement
    {
    }
    

    Then add a requirement handler

    public class TeamAccessHandler : AuthorizationHandler
    {
        private readonly DbContext dbContext;
    
        public TeamAccessHandler(DbContext dbContext)
        {
            // example of an injected service. Put what you need here.
            this.dbContext = dbContext;
        }
    
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TeamAccessRequirement requirement)
        {
            // pattern matching is cool. if you can't do this, use context.Resource as AuthorizationFilterContext before and check for not null
            if (context.Resource is AuthorizationFilterContext authContext)
            {
                // you can grab the team id, (but no model builder to help you, sorry)
                var teamId = Guid.Parse(authContext.RouteData.Values["teamId"]);
    
                // now you can do the code you would have done in the guts of the actions.
                if (context.User.IsTeamAdmin(teamId))
                {
                    context.Succeed(requirement);
                }
                else
                {
                    context.Fail();
                }
            }
    
            return Task.CompletedTask;
        }
    }
    

    Then, you need to put this all together and enable it in the Startup.cs under ConfigureServices, like this:

        services.AddAuthorization(options =>
        {
            options.AddPolicy("HasAdminTeamAccess", policy =>
                policy.Requirements.Add(new TeamAccessRequirement()));
        });
    
        services.AddTransient();
    

    And finally, the usage:

    [HttpGet]
    [Authorize(Policy = "HasAdminTeamAccess")]
    public IActionResult ManageTeam(Guid teamId)
    { }
    

    Now your actions remain nice and clean. From here you can fine tune the policy by adding functionality to the requirements that you can call from the handler, or do whatever you want.

提交回复
热议问题