添加角色声明-我应该使用IClaimsTransformer吗

Lar*_*rsi 5 claims-based-identity authorize-attribute asp.net-web-api asp.net-identity .net-core

我们想在当前主体中添加很多角色声明(我们使用Authorize(Roles)属性),并发现IClaimsTransformer这看起来很合适。

我们已经registerd像这样

 app.UseClaimsTransformation(new ClaimsTransformationOptions
        {
            Transformer = new GetRolesFromDatabaseClaimsTransformer(new RoleManager2(Configuration.GetConnectionString("ourcoolapp")))
        });
Run Code Online (Sandbox Code Playgroud)

而变换是这样的:

public Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
{
        // A hacky way to not load on all requests. Better ideas?
        if (!context.Context.Request.Path.Value.Contains("api/"))
        {
            return Task.FromResult(context.Principal);
        }

        var roleClaims = RoleManager.GetRolesForUser(context.Principal.Identity.Name).Select(roleName => new Claim("role", roleName));

        var claims = new List<Claim> { };
        var identity = context.Principal.Identity as ClaimsIdentity;
        claims.AddRange(identity.Claims);
        claims.AddRange(roleClaims);

        var userIdentity = new ClaimsIdentity(claims, "local");
        var userPrinicpal = new ClaimsPrincipal(userIdentity);

        return Task.FromResult(userPrinicpal);
}
Run Code Online (Sandbox Code Playgroud)

问题:是否有其他或更聪明的方法来添加角色声明?

谢谢

Larsi

Sor*_*ren 4

另一个选择可能是UserClaimsPrincipalFactory

它提供了为给定用户创建声明主体的方法,您可以像 一样自定义它ClaimsTransformer

默认情况下,它添加UserNameUserId来声明集合。为了自定义它,您可以驱动UserClaimsPrincipalFactory并覆盖CreateAsync

public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<User, Role>
{
    public AppClaimsPrincipalFactory(UserManager<User> userManager,
        RoleManager<Role> roleManager,
        IOptions<IdentityOptions> optionsAccessor, 
        ILogger<AppClaimsPrincipalFactory> logger) 
        : base(userManager, roleManager, optionsAccessor)
    {
        logger.LogInformation("AppClaimsPrincipalFactory ctor");
    }

    public override async Task<ClaimsPrincipal> CreateAsync(User user)
    {
        var principal = await base.CreateAsync(user);
        ((ClaimsIdentity)principal.Identity).AddClaims(new []
        {
            new Claim("Foo", "Bar"), 
        });

        return principal;
    }
}
Run Code Online (Sandbox Code Playgroud)

并在DI中注册工厂:

services.AddScoped<IUserClaimsPrincipalFactory<User>,  AppClaimsPrincipalFactory>();  
Run Code Online (Sandbox Code Playgroud)

每当用户提出请求时,它将更改/覆盖该声明。
有关更多信息,请查看GitHub上的源代码。

  • 考虑到 ClaimsTransformer 和 UserClaimsPrincipalFactory 之间的区别在于,在 ClaimsTransformer 中,您可以动态更改声明(在每个请求中),但在其他情况下,您可以在第一次身份(SignInManager)声明请求时对其进行自定义,然后将声明保存在 cookie 中;) (3认同)