.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
相关产品推荐
相关产品推荐

