使用JwtBearerAuthentication返回404而非401的问题排查
遇到这种返回404而非预期401的情况,大概率是请求根本没匹配到带[Authorize]的控制器/Action,或者在认证校验环节之前就出现了路由相关的问题。结合你提供的代码,我整理了几个最可能的原因和对应的解决办法:
1. 路由配置不匹配(最常见的404原因)
如果你的带[Authorize]特性的控制器或Action没有正确配置路由,ASP.NET Core会找不到对应的资源,直接返回404,根本不会进入认证校验流程。
排查与解决:
- 检查控制器是否添加了路由特性,比如:
[Route("api/[controller]")] [Authorize] public class SecureController : Controller { // ... } - 确认Action上的HTTP方法特性(
[HttpGet]/[HttpPost]等)和你在Postman中使用的请求方法一致,比如Action是[HttpGet("info")],就不能用POST请求访问。 - 核对Postman中的请求URL是否完全匹配路由规则,比如控制器路由是
api/secure,Action路由是info,那正确的请求URL应该是GET /api/secure/info,不要出现拼写错误(比如少写字母、大小写问题)。
2. Token生成时的Audience参数错误
看你的Token生成代码,创建JwtSecurityToken时,第二个参数(受众Audience)传的是_configuration["JwtIssuer"],但在Startup的Token验证配置中,ValidAudience设置的是Configuration["JwtAudience"]。如果你的配置文件中JwtIssuer和JwtAudience是不同的值,会导致Token验证失败,但如果请求本身路由错误的话,你会先收到404,根本到不了认证失败的环节。
解决办法:
修正Token生成代码中的Audience参数,确保和验证配置一致:
var token = new JwtSecurityToken( _configuration["JwtIssuer"], _configuration["JwtAudience"], // 把这里改成JwtAudience claims, expires: expires, signingCredentials: creds );
3. 控制器访问修饰符问题
如果你的带[Authorize]的控制器是internal而不是public,ASP.NET Core的路由系统无法发现这个控制器,会直接返回404。
排查与解决:
检查控制器类的修饰符,确保是public:
[Authorize] [Route("api/[controller]")] public class SecureController : Controller // 这里必须是public { // ... }
4. 中间件顺序的小优化(不直接导致404,但影响代码整洁)
你的Configure方法中重复调用了app.UseAuthentication(),虽然这不会直接导致404,但没必要保留重复的调用,建议只保留一次,并且确保它在app.UseMvc()之前执行(你当前的顺序是对的,只是可以优化):
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseAuthentication(); // 只保留这一次即可 app.UseMvc(); }
先优先排查路由相关的问题,因为这是导致404最直接的原因,等解决了404问题后,如果还是出现认证失败的情况,再检查Token的配置是否正确。
内容的提问来源于stack exchange,提问作者Danijel Boksan

