升级JwtBearer相关NuGet包及.NET8后Claims为空的解决请求
问题:升级到.NET 8及JWT相关NuGet包后Claims为空的解决办法
问题描述
近期将项目迁移到.NET 8环境,同时升级了以下NuGet包:
- Microsoft.AspNetCore.Authentication.JwtBearer 从6.0.32 → 8.0.8
- System.IdentityModel.Tokens.Jwt 从6.36.0 → 8.0.2
除NuGet包更新外未做其他代码改动,但现在使用OAuth2.0的JWT令牌调用API时,Claims部分为空。相关授权配置及自定义角色处理程序代码如下:
授权配置代码
public void ConfigureServices(IServiceCollection services) { AddWebInfrastructure(services); AddCustom(services); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => { options.Authority = CommonConfiguration.Authority; options.Audience = ServiceConfiguration.Audience; options.TokenValidationParameters = new TokenValidationParameters() { RoleClaimType = "scope" }; }); var authorizeRole = ServiceConfiguration.AuthorizeRole; var isEnabled = ServiceConfiguration.EnableServiceAuthorization; services.AddAuthorization(auth => { auth.DefaultPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser() .Build(); auth.AddPolicy("CustomRole", policy => policy.Requirements.Add(new CustomRoleRequirement(authorizeRole, isEnabled))); }); services.AddHealthCheck(); }
自定义角色处理程序代码
public class CustomRoleHandler : AuthorizationHandler<CustomRoleRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRoleRequirement requirement) { if (!requirement.IsEnabled) { context.Succeed(requirement); return Task.CompletedTask; } var isMatched = context.User.HasClaim(c => c.Type.Equals("scope", StringComparison.OrdinalIgnoreCase) && c.Value.Equals(requirement.Role, StringComparison.OrdinalIgnoreCase)); if (isMatched) { context.Succeed(requirement); } return Task.CompletedTask; } } public class CustomRoleRequirement : IAuthorizationRequirement { public CustomRoleRequirement(string role, bool isEnabled) { Role = role; IsEnabled = isEnabled; } public string Role { get; set; } public bool IsEnabled { get; set; } }
解决步骤及代码修正
1. 修正TokenValidationParameters的赋值方式
.NET 8中直接实例化TokenValidationParameters会覆盖框架从Authority自动获取的默认验证配置(如签名密钥、Issuer校验规则等),导致令牌验证异常,无法解析Claims。应改为修改默认参数而非重新实例化:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => { options.Authority = CommonConfiguration.Authority; options.Audience = ServiceConfiguration.Audience; // 修改默认参数,而非覆盖整个TokenValidationParameters options.TokenValidationParameters.RoleClaimType = "scope"; });
2. 关闭默认Claim映射(避免命名空间干扰)
.NET 8默认会将JWT中的Claim类型映射到带有微软命名空间的格式(如http://schemas.microsoft.com/ws/2008/06/identity/claims/role),导致HasClaim无法匹配原始的scope类型。在AddAuthentication前添加以下配置关闭默认映射:
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
3. 注册自定义授权处理程序
原代码中未将CustomRoleHandler注入DI容器,框架无法调用该逻辑。需添加注册代码:
services.AddScoped<IAuthorizationHandler, CustomRoleHandler>();
完整修正后的ConfigureServices代码
public void ConfigureServices(IServiceCollection services) { // 关闭默认Claim映射,确保原始Claim类型不被修改 JwtSecurityTokenHandler.DefaultMapInboundClaims = false; AddWebInfrastructure(services); AddCustom(services); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => { options.Authority = CommonConfiguration.Authority; options.Audience = ServiceConfiguration.Audience; // 修改默认的TokenValidationParameters,保留框架自动配置的验证规则 options.TokenValidationParameters.RoleClaimType = "scope"; }); var authorizeRole = ServiceConfiguration.AuthorizeRole; var isEnabled = ServiceConfiguration.EnableServiceAuthorization; services.AddAuthorization(auth => { auth.DefaultPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser() .Build(); auth.AddPolicy("CustomRole", policy => policy.Requirements.Add(new CustomRoleRequirement(authorizeRole, isEnabled))); }); // 注册自定义角色授权处理程序 services.AddScoped<IAuthorizationHandler, CustomRoleHandler>(); services.AddHealthCheck(); }
关键原因说明
- .NET 8中JWT认证的默认配置逻辑变更,直接覆盖
TokenValidationParameters会丢失从授权服务器获取的核心验证规则,导致令牌验证失败,Claims无法解析。 - 默认Claim映射会修改原始Claim的类型名称,导致自定义验证逻辑无法匹配目标Claim。
- 自定义授权处理程序必须注入DI容器才能被框架识别并执行。
内容的提问来源于stack exchange,提问作者Nikhil Srivastava
相关产品推荐
相关产品推荐

