ASP.NET Core 2.0多认证方案中JWT Token调用API异常排查
看起来你遇到的核心问题是:即使API方法指定了JWT认证方案,认证失败时系统还是触发了Cookie认证的跳转逻辑(返回302到登录页),而非返回JWT对应的401未授权响应。Postman显示200是因为它自动跟随了302跳转,最终拿到的是登录页的HTML内容,而非API的预期响应。
问题根源
在你的配置中,DefaultChallengeScheme被设置为"my_cookie",这意味着当任何认证方案触发Challenge(认证失败)时,默认会使用Cookie方案的跳转逻辑。虽然你在API方法上指定了[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)],但ASP.NET Core 2.0在处理JWT认证失败时,还是会回退到全局的DefaultChallengeScheme,导致跳转到登录页。
解决方案
1. 覆盖JwtBearer的Challenge事件,禁用跳转行为
修改你的JwtBearer配置,添加OnChallenge事件处理,强制返回401响应而不是跳转:
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtBearerOptions => { jwtBearerOptions.RequireHttpsMetadata = false; jwtBearerOptions.SaveToken = true; jwtBearerOptions.Challenge = JwtBearerDefaults.AuthenticationScheme; jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("my_secret_key")), ValidateIssuer = true, ValidIssuer = "myapp-api", ValidateAudience = true, ValidAudience = "myapp-client", ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes(5) }; // 新增:处理JWT认证失败时的Challenge逻辑,禁止跳转 jwtBearerOptions.Events = new JwtBearerEvents { OnChallenge = context => { // 阻止默认的跳转响应 context.HandleResponse(); if (!context.Response.HasStarted) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; context.Response.ContentType = "application/json"; var errorResponse = Newtonsoft.Json.JsonConvert.SerializeObject( new { Message = "Invalid or missing JWT token" } ); return context.Response.WriteAsync(errorResponse); } return Task.CompletedTask; } }; })
2. 确保认证中间件的顺序正确
在Startup.cs的Configure方法中,必须在UseMvc()之前调用UseAuthentication(),否则认证逻辑不会生效:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // 其他中间件(如异常处理、静态文件等)... app.UseAuthentication(); // 这行必须在UseMvc之前 app.UseMvc(); }
3. 验证Postman请求的正确性
确认你的Postman请求符合要求:
- 请求头中包含
Authorization,格式为Bearer <你的JWT Token>(注意Bearer后面有空格) - 使用JWT解码工具验证Token的
iss(Issuer)、aud(Audience)和签名密钥是否与你的配置完全匹配 - 确保Token未过期
额外检查点
如果你使用的是ASP.NET Core 2.0,还要确认AddAuthentication的配置中,JWT方案的名称是否与Authorize属性中指定的一致(你用了JwtBearerDefaults.AuthenticationScheme,也就是"Bearer",这部分是正确的)。
内容的提问来源于stack exchange,提问作者Sam

