.NET 8升级后System.IdentityModel.Tokens.Jwt获取对象声明异常
.NET 8升级后JWT Claim对象无法序列化为JSON的问题解决
问题原因
在适配.NET 8的新版System.IdentityModel.Tokens.Jwt组件中,SecurityTokenDescriptor.Claims对object类型值的处理逻辑发生了变更:
- 旧版本(如6.15.1)会自动将复杂对象序列化为JSON字符串,并将Claim的
ValueType标记为"JSON"; - 新版本默认仅调用对象的
ToString()方法,因此解析时得到的是类型的完全限定名(如Namespace.ClassA),而非预期的JSON内容。
解决方案
方案1:手动序列化复杂对象为JSON字符串
在构造Claims字典时,提前将复杂对象序列化为JSON字符串,确保JWT中存储的是可反序列化的JSON内容。
修改GetClaims方法:
public Dictionary<string, object> GetClaims() { List<Permission> somePermissions = [ new Permission { Name = "SomeName", Level = "SomeLevel", ExtraInfo = ["A","B","C"] } ]; var result = new Dictionary<string, object> { { "DictionaryKey", JsonConvert.SerializeObject(somePermissions) // 手动序列化为JSON字符串 } }; return result; }
方案2:直接构造指定ValueType的Claim对象
绕过SecurityTokenDescriptor.Claims字典,直接在ClaimsIdentity中创建标记ValueType为JsonClaimValueTypes.Json的Claim对象,明确告知JWT处理器该值为JSON类型。
修改生成JWT的核心代码:
// 获取权限数据 var somePermissions = new List<Permission> { new Permission { Name = "SomeName", Level = "SomeLevel", ExtraInfo = ["A","B","C"] } }; // 构造带JSON类型标记的Claim var claims = new List<Claim> { // 其他业务Claim... new Claim("DictionaryKey", JsonConvert.SerializeObject(somePermissions), JsonClaimValueTypes.Json) }; var securityTokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), // 过期时间、签名密钥等其他配置... }; // 生成并返回Token return _jwtSecurityTokenHandler.WriteToken( _jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor) );
解析代码调整(无需大幅修改)
解析时直接使用Claim的Value进行反序列化即可:
var claimsPrincipal = ReturnTokenClaimsPrincipal(token); var permissionClaim = claimsPrincipal.FindFirst("DictionaryKey"); if (permissionClaim != null) { var permissions = JsonConvert.DeserializeObject<List<Permission>>(permissionClaim.Value); // 后续业务逻辑处理 }
内容的提问来源于stack exchange,提问作者samalk
相关产品推荐
相关产品推荐

