JWT刷新后长度异常增大的原因是什么?有什么处理方案?
问题原因
这是.NET中JwtSecurityTokenHandler类的默认Claim类型映射机制导致的:
- 第一次生成JWT时,你用
ClaimTypes枚举定义的声明本质是内置的URI格式常量,生成令牌时JwtSecurityTokenHandler会按照内置映射规则,自动把这些长URI映射为unique_name、role、email这类短名称写入JWT的Payload。 - 当你验证旧令牌获取
ClaimsPrincipal时,入站验证逻辑又会自动把JWT里的短声明名称,反向映射回原本的长URI格式作为Claim的Type存储在内存中。 - 刷新令牌时你直接把这些带有长URI Type的Claim传入新令牌的生成逻辑,此时没有触发反向的短名映射,直接把长URI作为Payload的键写入,最终导致令牌长度翻倍。
解决方案
方案1:全局关闭默认Claim类型映射(推荐)
在程序启动入口(如.NET 6+的Program.cs文件顶部)添加以下代码,清空默认的入站、出站Claim映射规则:
// 清空入站Claim类型映射,验证令牌时不会把短名转成长URI JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // 清空出站Claim类型映射,生成令牌时不会自动转换Claim名称 JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
修改后验证令牌得到的ClaimsPrincipal中的Claim Type会和JWT Payload里的短名完全一致,刷新生成的新令牌也会沿用短名,长度和初始令牌一致。
方案2:刷新令牌时手动转换Claim名称
如果不想修改全局映射,可以在刷新令牌时手动处理Claim,替换掉长URI前缀:
var claims = principle.Claims.Select(c => { var shortType = c.Type switch { "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" => "unique_name", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" => "role", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" => "email", _ => c.Type }; return new Claim(shortType, c.Value); }); var jwtSecurityToken = new JwtSecurityToken( claims: claims.ToArray(), notBefore: DateTime.UtcNow, expires: DateTime.UtcNow.AddMinutes(1), signingCredentials: new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256) );
方案3:生成初始令牌时直接使用短字符串作为Claim类型
创建Claim时不使用ClaimTypes的常量,直接传入自定义短名称,从根源避免映射转换:
Subject = new ClaimsIdentity(new Claim[]{ new Claim("unique_name",username), new Claim("role",myrole), new Claim("email",myemail) }),
内容的提问来源于stack exchange,提问作者Yuvraj Mule
相关产品推荐
相关产品推荐

