.NET 6中JWT Bearer Token授权失败(401 Unauthorized)求助
.NET 6 JWT授权401错误排查方向
以下是针对你遇到的「已生成JWT Token但访问带[Authorize]特性的接口返回401」问题的具体排查点:
1. 严格校验Issuer/Audience的完全一致性
- 确保生成Token时的Issuer、Program.cs中验证的ValidIssuer、appsettings.json中的JWT:Issuer三者完全匹配,包括协议(http/https)、端口、是否带结尾斜杠,甚至大小写。比如你修改为
https://localhost:7139后,要检查三处是否都统一为这个值,不能一处是http另一处是https。 - 同理Audience(JWT:Audience)也要保持完全一致,你的配置中是
user,确认生成和验证逻辑都使用这个值。
2. 检查请求中Token的携带方式
- 访问接口时,必须在请求头中添加
Authorization字段,格式为Bearer <你的Token>,注意Bearer和Token之间有一个空格。 - 排查是否存在字段拼写错误(比如把Authorization写成Auth),或者Token被截断、复制不全的情况。
3. 确认Secret的完全匹配
- 生成Token时使用的
JWT:Secret和验证时的Secret必须完全一致,包括字符大小写、特殊符号、前后空格。你当前用的是this-is-just-a-strong-key,检查三处代码(GenerateJWTToken、Program.cs、appsettings.json)是否都引用了同一个配置,且配置值无额外空格。 - 注意:如果Secret包含非ASCII字符,需将
Encoding.ASCII.GetBytes改为Encoding.UTF8.GetBytes,避免字符编码不一致导致签名验证失败。
4. 解析Token验证核心字段有效性
- 把生成的Token复制到本地解析工具(如jwt.io,仅本地解析无需上传),检查以下内容:
- Payload中的
iss是否与配置的Issuer完全一致 aud是否为userexp是否未过期(当前时间早于exp对应的时间)- 签名栏是否显示「Signature verified」,如果未验证通过,说明Secret不匹配或Token被篡改。
- Payload中的
5. 确认中间件注册顺序
- 在Program.cs中,必须先调用
app.UseAuthentication(),再调用app.UseAuthorization(),如果顺序颠倒,授权逻辑会在认证之前执行,导致401错误。
6. 检查HTTPS相关配置矛盾
- 你的Program.cs中设置了
options.RequireHttpsMetadata = false,如果服务实际运行在HTTPS环境(比如你用的https://localhost:7139),此配置本身没问题,但要确保请求是通过HTTPS发送的,避免协议不匹配。
附你提供的代码片段
AuthController.cs(生成Token逻辑)
private async Task<AuthResultVM> GenerateJWTToken(User user) { var authClaims = new List<Claim>() { new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.NameIdentifier, user.Id), new Claim(JwtRegisteredClaimNames.Email, user.Email), new Claim(JwtRegisteredClaimNames.Sub, user.Email), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; var authSignInKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_configuration["JWT:Secret"])); var token = new JwtSecurityToken( issuer: _configuration["JWT:Issuer"], audience: _configuration["JWT:Audience"], expires: DateTime.UtcNow.AddDays(7), claims: authClaims, signingCredentials: new SigningCredentials(authSignInKey, SecurityAlgorithms.HmacSha256) ); var jwtToken = new JwtSecurityTokenHandler().WriteToken(token); var response = new AuthResultVM() { Token = jwtToken, ExpiresAt = token.ValidTo }; return response; }
AccountController(授权接口)
[ApiController] [Route("api/[controller]")] [Authorize] public class AccountController : ControllerBase { private readonly IMapper _mapper; public AccountController(IMapper mapper) { _mapper = mapper; } [HttpGet] public ActionResult Get() { return Ok("This is the AccountContoller"); } }
appsettings.json(配置文件)
"JWT": { "Secret": "this-is-just-a-strong-key", "Audience": "user", "Issuer": "http://localhost:44347" // 已将Issuer修改为localhost:7139,但仍出现401错误 }
Program.cs(认证配置)
// 其他代码 builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.SaveToken = true; options.RequireHttpsMetadata = false; options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(builder.Configuration["JWT:Secret"])), ValidateIssuer = true, ValidIssuer = builder.Configuration["JWT:Issuer"], ValidateAudience = true, ValidAudience = builder.Configuration["JWT:Audience"], }; }); //其他代码
内容的提问来源于stack exchange,提问作者DonDavid12
相关产品推荐
相关产品推荐

