如何在.NET Core 6.0中从JWT安全令牌读取自定义声明值
解决方案
1. 自定义声明丢失的核心修复
这是由于ASP.NET Core JWT处理程序默认开启了声明类型映射,会自动将短声明名转换为XML SOAP标准的长URI格式,未匹配到映射规则的自定义声明会被过滤。
在Program.cs的AddAuthentication配置前添加一行代码清除默认映射:
// 清除默认声明类型映射,保留自定义声明的原始名称 JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); builder.Services.AddAuthentication(m => { m.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; m.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(conf => { conf.RequireHttpsMetadata = false; conf.SaveToken = true; conf.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidIssuer = Configuration["JWT-Issuer"], ValidAudience = Configuration["JWT-Issuer"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT-Key"])), ClockSkew = TimeSpan.Zero, // 可选:添加签名密钥校验提升安全性 ValidateIssuerSigningKey = true, // 可选:如果要使用[Authorize(Roles="xxx")]特性,指定角色声明的类型 RoleClaimType = "Role" }; });
配置完成后,你的自定义声明TEMP、UserName都会原样保留在User.Claims中。
2. 读取声明代码优化
清除映射后,内置声明的类型也会还原为短名称,你可以直接用原始声明名读取,无需匹配长URI:
// 读取邮箱 string Email = User.FindFirstValue(JwtRegisteredClaimNames.Email); // 读取自定义TEMP声明 string FirstName = User.FindFirstValue("TEMP");
FindFirstValue是官方封装的简化方法,找不到对应声明时会返回null,避免空引用异常。
3. 显式设置DefaultAuthenticateScheme返回401的问题修复
你现在只设置DefaultScheme就可以覆盖所有身份验证相关的默认方案,本身不需要额外调整。如果要显式配置DefaultAuthenticateScheme,只需检查两个配置点:
- 确认中间件顺序正确,
Program.cs中必须先调用app.UseAuthentication(),再调用app.UseAuthorization(),顺序错误会直接导致401 - 如果你的项目同时集成了ASP.NET Core Identity,不要使用
AddIdentity扩展方法,改用AddIdentityCore,前者会默认覆盖身份验证方案为Cookie,导致JWT配置失效
不需要创建自定义身份验证方案,按上述配置调整即可解决所有问题。
内容的提问来源于stack exchange,提问作者Saqlain Mushtaq
相关产品推荐
相关产品推荐

