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

.NET 5升级至.NET 6后JWT Token认证失效问题排查求助

排查.NET 6 Web API JWT授权返回“Unauthorized”问题

问题背景

将.NET 5.0 Web API迁移至.NET 6.0后,原正常运行的JWT授权功能出现“Unauthorized”错误,未添加[Authorize]特性的API可正常工作,当前Program.cs代码如下:

var builder = WebApplication.CreateBuilder(args);
var provider = builder.Services.BuildServiceProvider();
var Configuration = provider.GetRequiredService<IConfiguration>();


builder.Services.AddCors(options =>
{
    options.AddPolicy(
        "Open",
        builder => builder.AllowAnyOrigin().AllowAnyHeader());
});

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "tEST.Services", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference= new OpenApiReference
                            {
                                Type= ReferenceType.SecurityScheme,
                                Id="Bearer"
                            }
                        }, new string[] { }

                    }
                });
});

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
              .AddJwtBearer(options =>
              {
                  options.TokenValidationParameters = new TokenValidationParameters
                  {
                      ValidateIssuer = true,
                      ValidateAudience = true,
                      ValidateLifetime = true,
                      ValidateIssuerSigningKey = true,
                      ValidIssuer = Configuration["Jwt:Issuer"],
                      ValidAudience = Configuration["Jwt:Audience"],
                      IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
                  };

                  options.Events = new JwtBearerEvents
                  {
                      OnAuthenticationFailed = context =>
                      {
                          if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                          {
                              context.Response.Headers.Add("Token-Expired", "true");
                          }
                          return Task.CompletedTask;
                      }
                  };
              });

builder.Services.AddSingleton<IConfiguration>(Configuration);

问题根源及修复方案

1. 冗余的ServiceProvider构建

代码中提前构建ServiceProvider获取IConfiguration属于多余操作,.NET 6的WebApplicationBuilder自带Configuration属性,直接使用builder.Configuration即可,无需额外注册单例IConfiguration。

2. 缺失授权服务注册

需显式添加授权服务注册,确保授权系统正常初始化:

builder.Services.AddAuthorization();

3. 中间件顺序错误

.NET 6中中间件顺序直接决定功能是否生效,必须按以下顺序配置:

  • 先启用Cors
  • 再启用认证(UseAuthentication)
  • 然后启用授权(UseAuthorization)
  • 最后映射控制器(UseControllers)

修复后的完整Program.cs代码

var builder = WebApplication.CreateBuilder(args);

// 直接使用builder.Configuration,无需提前构建ServiceProvider
var configuration = builder.Configuration;

builder.Services.AddCors(options =>
{
    options.AddPolicy(
        "Open",
        policyBuilder => policyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "tEST.Services", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference= new OpenApiReference
                {
                    Type= ReferenceType.SecurityScheme,
                    Id="Bearer"
                }
            }, Array.Empty<string>()
        }
    });
});

// 先添加认证,再添加授权
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
              .AddJwtBearer(options =>
              {
                  options.TokenValidationParameters = new TokenValidationParameters
                  {
                      ValidateIssuer = true,
                      ValidateAudience = true,
                      ValidateLifetime = true,
                      ValidateIssuerSigningKey = true,
                      ValidIssuer = configuration["Jwt:Issuer"],
                      ValidAudience = configuration["Jwt:Audience"],
                      IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"]))
                  };

                  options.Events = new JwtBearerEvents
                  {
                      OnAuthenticationFailed = context =>
                      {
                          if (context.Exception is SecurityTokenExpiredException)
                          {
                              context.Response.Headers.Add("Token-Expired", "true");
                          }
                          return Task.CompletedTask;
                      }
                  };
              });

// 显式添加授权服务
builder.Services.AddAuthorization();

var app = builder.Build();

// 中间件顺序必须严格遵循
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

// 先启用Cors
app.UseCors("Open");

// 再启用认证
app.UseAuthentication();

// 然后启用授权
app.UseAuthorization();

// 最后映射控制器
app.MapControllers();

app.Run();

额外验证点

  • 确认appsettings.json中的Jwt:Issuer、Jwt:Audience、Jwt:Key配置与生成JWT时的参数完全一致
  • 确保请求头中的Authorization格式为Bearer {token},无拼写错误或空格问题
  • 可临时关闭ValidateIssuer、ValidateAudience验证,排查是否为配置不匹配导致的问题

内容的提问来源于stack exchange,提问作者Ismail

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:24:32