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

升级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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:20:03