使用参数进行团队成员身份的ASP.NET核心身份授权

Val*_*tor 6 c# asp.net-core asp.net-core-identity

我有一个像这样的表的应用程序:

  • 用户(ASP.NET核心标识)
  • 球队
  • UserTeam(多对多连接表)

用户可以是多个团队的成员,并且可以在团队中具有不同的角色.例如,用户可能是TeamA的TeamAdmin,但只是TeamB的普通成员.因此,使用静态值定义的简单角色检查和策略将不起作用.

我正在寻找一种方法来根据用户团队及其在团队中的角色为用户授权控制器操作,这些操作将作为声明或单独的RoleTeam表添加.假设Controller操作如下:

[HttpGet]
[Authorize(???)]
public IActionResult ManageTeam(Guid teamId)
{ }
Run Code Online (Sandbox Code Playgroud)

我需要验证用户是否具有相关团队的TeamAdmin角色.是否有一种干净的方法来使用可以访问teamId参数的Authorize属性来装饰它?或者我是否必须在if (User.IsTeamAdmin(teamId)......语句中包含所有这些操作的内容?

Bal*_*lah 10

ASP.NET Core引入了可应用于Authorize属性的策略概念.像过滤器一样工作,但没有编写过滤器.

每个策略都有一个或多个要求,必须满足策略才能通过.在微软的文档具有设置策略的一个很好的例子.在你的情况下,我会做类似以下的事情:

首先,从"要求"开始

public class TeamAccessRequirement : IAuthorizationRequirement
{
}
Run Code Online (Sandbox Code Playgroud)

然后添加需求处理程序

public class TeamAccessHandler : AuthorizationHandler<TeamAccessRequirement>
{
    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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要将所有这些放在一起,并在Startup.cs下面启用它ConfigureServices,如下所示:

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

    services.AddTransient<IAuthorizationHandler, TeamAccessHandler>();
Run Code Online (Sandbox Code Playgroud)

最后,用法:

[HttpGet]
[Authorize(Policy = "HasAdminTeamAccess")]
public IActionResult ManageTeam(Guid teamId)
{ }
Run Code Online (Sandbox Code Playgroud)

现在你的行动保持干净整洁.从这里,您可以通过向可以从处理程序调用的需求添​​加功能来微调策略,或者执行您想要的任何操作.