ASP.NET Core 8 JWT生成异常致REST客户端认证失败排查
ASP.NET Core 8 JWT认证在API接口返回401重定向的问题
问题背景
已为ASP.NET Core 8 Web应用配置JWT令牌认证,该配置在带[Authorize]特性的MVC视图控制器中正常工作,但在REST API接口中,客户端(.NET Framework 4.0 WPF应用)通过请求头携带Bearer令牌认证时,返回401重定向页面的HTML,认证失败。Postman也能复现该问题。
认证配置代码(Startup.cs)
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.SaveToken = true; options.RequireHttpsMetadata = false; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ClockSkew = TimeSpan.Zero, ValidAudience = Configuration["Jwt:Audience"], ValidIssuer = Configuration["Jwt:Issuer"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])), }; });
令牌生成代码
[AllowAnonymous] [HttpPost] public async Task<IActionResult> Index(LoginUserUser usr) { IActionResult response = Unauthorized(); var user = await userManager.FindByNameAsync(usr.username); if (user != null && await userManager.CheckPasswordAsync(user, usr.password)) { var userRoles = await userManager.GetRolesAsync(user); var authClaims = new List<Claim> { new(ClaimTypes.Name, user.UserName), new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), }; foreach (var userRole in userRoles) { authClaims.Add(new Claim(ClaimTypes.Role, userRole)); } var token = CreateToken(authClaims); var refreshToken = GenerateRefreshToken(); user.RefreshToken = refreshToken; var refreshTokenValidityInDays = Convert.ToInt32(Configuration["Jwt:RefreshTokenValidityInDays"]); user.RefreshTokenExpiryTime = DateTime.Now.AddDays(refreshTokenValidityInDays); await userManager.UpdateAsync(user); response = Ok(new { access_token = new JwtSecurityTokenHandler().WriteToken(token) }); } return response; } private JwtSecurityToken CreateToken(List<Claim> authClaims) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var result = new JwtSecurityToken( issuer: Configuration["Jwt:Issuer"], audience: Configuration["Jwt:Audience"], claims: authClaims, expires: DateTime.Now.AddMinutes(1440), signingCredentials: credentials); return result; }
排查进展
- 已验证令牌有效:通过jwt.ms确认签名验证通过,Issuer和Audience与配置一致(使用本地应用URL)
- 确认客户端请求携带的令牌正确
排查方向
- 检查中间件顺序:确保
app.UseAuthentication()在app.UseAuthorization()之前,且位于app.UseRouting()之后。若项目同时启用MVC Cookie认证,需避免其默认重定向逻辑干扰API接口。 - 禁用JWT挑战重定向:API接口应返回JSON格式401而非HTML页面,可在JWT配置中添加事件处理:
options.Events = new JwtBearerEvents { OnChallenge = context => { context.HandleResponse(); context.Response.StatusCode = StatusCodes.Status401Unauthorized; context.Response.ContentType = "application/json"; return context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(new { message = "Unauthorized" })); } }; - 指定API控制器的认证方案:在API控制器的
[Authorize]特性中明确指定JWT方案,避免默认使用Cookie认证:[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - 校验请求头格式:确认客户端请求的
Authorization头严格遵循Bearer {token}格式,无多余空格或拼写错误。 - 核对协议一致性:确保令牌中的Issuer/Audience协议(http/https)与请求协议一致,避免因协议不匹配导致验证失败。
内容的提问来源于stack exchange,提问作者Igor Kondrasovas
相关产品推荐
相关产品推荐

