在 .net 8 Blazor Identity 中添加Claim

.net 8 Blazor Identity 使用 Individual Account 模版时,默认的UserInfo 只有Id,Email 和 UserName。 如果想让客户端共享更多用户信息,可以使用自定义的ClaimsPrincipalFactory。代码如下:

public class FlowYogaClaimsPrincipalFactory(UserManager<YourCustomUserClass> userManager, RoleManager<IdentityRole> roleManager, IOptions<IdentityOptions> optionsAccessor)
    : UserClaimsPrincipalFactory<YourCustomUserClass, IdentityRole>(userManager, roleManager, optionsAccessor)
{
    protected override async Task<ClaimsIdentity> GenerateClaimsAsync(YourCustomUserClass user)
    {
        var identity = await base.GenerateClaimsAsync(user);
        identity.AddClaim(new Claim("Nick", $"{user.Nick}"));
        identity.AddClaim(new Claim("Nick", $"{user.Icon}"));
        return identity;
    }
}

 这里我加入了用户的昵称和图标两个新值。服务端序列化时要修改 PersistingRevalidatingAuthenticationStateProvider.cs

private async Task OnPersistingAsync()
{
    if (authenticationStateTask is null)
    {
        throw new UnreachableException($"Authentication state not set in {nameof(OnPersistingAsync)}().");
    }

    var authenticationState = await authenticationStateTask;
    var principal = authenticationState.User;

    if (principal.Identity?.IsAuthenticated == true)
    {
        var userId   = principal.FindFirst(options.ClaimsIdentity.UserIdClaimType)?.Value;
        var email    = principal.FindFirst(options.ClaimsIdentity.EmailClaimType)?.Value;
        var userName = principal.FindFirst(options.ClaimsIdentity.UserNameClaimType)?.Value;
        var nick     = principal.FindFirst("Nick")?.Value;
        var icon     = principal.FindFirst("Icon")?.Value;
        
        if (userId != null && email != null)
        {
            state.PersistAsJson(nameof(UserInfo), new UserInfo
            {
                UserName = userName,
                UserId = userId,
                Email = email,
                Nick = nick,
                Icon = icon
            });
        }
    }
}

 WASM客户端工程里的PersistentAuthenticationStateProvider.cs也要修改:

public PersistentAuthenticationStateProvider(PersistentComponentState state)
{
    if (!state.TryTakeFromJson<UserInfo>(nameof(UserInfo), out var userInfo) || userInfo is null)
    {
        return;
    }

    Claim[] claims =
    [
        new Claim(ClaimTypes.NameIdentifier, userInfo.UserId),
        new Claim(ClaimTypes.Name, userInfo.UserName),
        new Claim(ClaimTypes.Email, userInfo.Email),
        new Claim("Nick", userInfo.Nick),
        new Claim("Icon", userInfo.Icon)
    ];

    authenticationStateTask = Task.FromResult(
        new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims,
            authenticationType: nameof(PersistentAuthenticationStateProvider)))));
}

 WASM组件读取就可以了

<AuthorizeView>
    Hello @context.User.Identity?.Name!

    <br />Your Nick: @context.User.FindFirst("Nick")?.Value

</AuthorizeView>

 

posted @ 2024-01-20 09:43  LegoCodr  阅读(169)  评论(0)    收藏  举报