ASP.NET Core 2.0 如何在策略中访问UserManager?

ASP.NET Core 2.0 How to access UserManager in a policy?

我有这个要求 class 需要访问 usermanager

public class NoAdminRequirment : IAuthorizationRequirement
{
    bool NoAdmins { get; set; }
    private readonly UserManager<IdentityUser> userManager;

    public NoAdminRequirment(UserManager<IdentityUser> userManager)
    {
        this.userManager = userManager;
            NoAdmins = userManager.GetUsersInRoleAsync("administrators").Result.Count() == 0;
    }
}

我的理解是 usermanager 是通过依赖注入自动初始化的,因为我在我的应用程序中设置了它

嗯,这不是很有用,因为我现在需要在策略中传递用户管理器

services.AddAuthorization(option =>
{
    option.AddPolicy("NoAdmins", policy => policy.Requirements.Add(new { /*???*/ }));
});

有人可以建议替代方法或访问用户管理器的方法吗?

services.AddAuthorization(option => {
    option.AddPolicy("NoAdmins", policy => 
                policy.Requirements.Add(services.BuildServiceProvider().GetService<NoAdminRequirment>()));
});

我认为这应该可以解决问题:

public class ExcludeRoleRequirement : IAuthorizationRequirement
{
  public string Role { get; private set; }

  public ExcludeRoleRequirement(string role)
  {
    Role = role;
  }
}

由于 ExcludeRoleHandler 已注册到 DI 容器,我假设 UserManager 也已注册,您可以将 UserManager 添加到构造函数

public class ExcludeRoleHandler : AuthorizationHandler<ExcludeRoleRequirement>
{
  private readonly UserManager<IdentityUser> _manager;
  public ExcludeRoleHandler(UserManager<IdentityUser> manager)
  {
    _manager = manager;
  }
  protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, 
    ExcludeRoleRequirement requirement)
  {
    var usersInRole = await _manager.GetUsersInRoleAsync(requirement.Role);
    if (!usersInRole.Any())
    {
      context.Succeed(requirement);
    }

    return Task.CompletedTask;
  }
}

然后在 Startup.cs:

services.AddAuthorization(option => {
  options.AddPolicy("NoAdmin", policy =>
    policy.Requirements.Add(new ExcludeRoleRequirement("administrators")));  
});


services.AddSingleton<IAuthorizationHandler, ExcludeRoleHandler>();

希望对您有所帮助

编辑:我忘了添加

[Authorize(Policy = "NoAdmin")]
public class NotForAdminController : ControllerBase
{
}