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

.NET Core 6中JWT令牌验证失败,始终返回401错误求助

JWT验证返回401错误的排查与修复

问题描述

实现JWT令牌生成及认证配置后,访问受保护API时始终返回401错误,令牌验证不通过。

相关代码片段

Program.cs 认证配置代码

builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWTToken_Auth_Api", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = @"JWT Authorization header using the Bearer scheme. \r\n\r\n 
                      Enter 'Bearer' [space] and then your token in the text input below.
                      \r\n\r\nExample: 'Bearer 12345abcdef'",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        BearerFormat = "JWT",
        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.RequireHttpsMetadata = false;
    options.SaveToken = true;
    options.IncludeErrorDetails = true;
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = false,
        ValidAudience = builder.Configuration["Jwt:Audience"],
        ValidIssuer = builder.Configuration["Jwt:Issuer"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
    };
});

控制器令牌生成方法代码

[NonAction]
public string GetToken(LoginUser loginUser)
{
    var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Sub, _configuration["Jwt:Subject"]),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
            new Claim("UserId", loginUser.UserLogin),
            new Claim("Name", loginUser.FirstName +" "+ loginUser.LastName),
            new Claim("Email", loginUser.Email)
        };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
    var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var token = new JwtSecurityToken(
            _configuration["Jwt:Issuer"],
            _configuration["Jwt:Audience"],
            claims,
            expires: DateTime.UtcNow.AddMinutes(10),
            signingCredentials: signIn);

    string Token = new JwtSecurityTokenHandler().WriteToken(token);

    return Token;
}

错误原因及修复方案

1. 签名密钥验证未启用

在TokenValidationParameters中,ValidateIssuerSigningKey被设置为false,这会跳过令牌签名合法性验证,即使密钥不匹配也不会拦截,直接导致认证逻辑失效。

修复:
将该参数改为true:

ValidateIssuerSigningKey = true,

2. 认证中间件缺失或顺序错误

如果Program.cs中未添加app.UseAuthentication()和app.UseAuthorization(),或者中间件顺序错误,认证逻辑不会被触发,直接返回401。

修复:
在中间件管道中添加以下代码,注意顺序必须在app.UseRouting()之后、app.UseEndpoints()之前:

app.UseAuthentication();
app.UseAuthorization();

3. Iat声明格式不符合JWT标准

生成令牌时,JwtRegisteredClaimNames.Iat被设置为字符串格式的当前时间,但JWT标准要求Iat(签发时间)为Unix时间戳数值类型,格式错误会导致生命周期验证失败。

修复:
修改Iat声明的生成方式:

new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64),

4. 配置项一致性检查

确保appsettings.json中的JWT配置项与生成、验证逻辑完全匹配:

  • 检查Jwt:Key长度:HmacSha256算法要求密钥至少128位(16个UTF-8字符以上),过短的密钥会导致验证失败。
  • 确认Jwt:Issuer和Jwt:Audience无拼写错误,生成令牌与验证时使用的是同一配置值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:17:06