You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8 Blazor Server中IClaimsTransformation添加的Claims无法持久化

问题原因

你遇到的核心问题是:IClaimsTransformation每次处理的ClaimsPrincipal都是从认证Cookie里重新反序列化出来的原始对象,不是上一次修改后留存的实例。

你的认证方案是Cookie+OpenID Connect,用户登录后的身份信息最终存在Cookie中。每次请求(包括Blazor Server的SignalR交互)都会从Cookie读取并反序列化为ClaimsPrincipal,再传给TransformAsync。你之前添加的TEST Claim只存在于当前请求的内存里,没有被持久化到Cookie,所以下一次调用TransformAsync时,传入的principal还是没有TEST Claim的原始状态,自然每次都得重新加。

不管是修改现有身份还是新建身份,只要不把修改后的ClaimsPrincipal写入Cookie,下一次请求都会回到原始状态,这就是两种添加方式都无效的原因。

解决方案

推荐两种实用的解决办法:

办法一:用Cookie认证的OnValidatePrincipal事件(更推荐)

直接在AddCookie的配置里绑定验证事件,添加Claim后标记更新Cookie,这样修改会被持久化:

.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
    options.AccessDeniedPath = "/statuscode/401";
    options.Events = new CookieAuthenticationEvents
    {
        async OnValidatePrincipal(CookieValidatePrincipalContext context)
        {
            if (!context.Principal.HasClaim(c => c.Type == "TEST"))
            {
                var identity = context.Principal.Identity as ClaimsIdentity;
                identity.AddClaim(new Claim("TEST", "TESTVALUE"));
                
                // 告诉中间件更新Cookie,把修改后的身份信息存进去
                context.ShouldRenew = true;
            }
        }
    };
})

这样处理后,下一次请求加载Cookie时,Principal就已经包含TEST Claim了,不用每次都添加。

办法二:在IClaimsTransformation中手动更新Cookie

给MyClaimsTransformation注入认证服务和HttpContext访问器,添加Claim后重新登录用户以更新Cookie:

public class MyClaimsTransformation : IClaimsTransformation
{
    private readonly IAuthenticationService _authService;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyClaimsTransformation(IAuthenticationService authService, IHttpContextAccessor httpContextAccessor)
    {
        _authService = authService;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var identity = principal.Identity as ClaimsIdentity;
        if (identity != null && !principal.HasClaim(c => c.Type == "TEST"))
        {
            identity.AddClaim(new Claim("TEST", "TESTVALUE"));
            
            // 重新登录,把修改后的身份写入Cookie
            await _authService.SignInAsync(
                _httpContextAccessor.HttpContext,
                CookieAuthenticationDefaults.AuthenticationScheme,
                principal,
                new AuthenticationProperties { IsPersistent = true });
        }

        return principal;
    }
}

⚠️ 注意:一定要加Claim存在性判断,避免SignInAsync触发TransformAsync导致无限循环。

补充提示

Blazor Server用SignalR长连接,IClaimsTransformation确实会被多次调用,但只要把Claim持久化到Cookie,后续调用时传入的Principal就会自带TEST Claim,不用重复添加。另外你设置了UseTokenLifetime = false,Cookie有效期默认是14天,持久化的Claim会在有效期内一直有效。

内容的提问来源于stack exchange,提问作者Schoof

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 09:59:52