为何已配置JwtBearer默认认证Scheme,独立Authorize不生效
该问题的核心原因是默认认证Scheme没有被正确关联到[Authorize]特性的默认执行逻辑,常见原因及对应排查方案按优先级排序如下:
1. 中间件管道顺序错误(最高发)
ASP.NET Core 3.0+ 采用终结点路由模式后,认证、授权中间件的调用顺序有严格要求,正确的管道顺序必须是:
app.UseRouting(); // 先解析请求对应的终结点 app.UseAuthentication(); // 再执行认证逻辑,解析请求中的Token app.UseAuthorization(); // 最后执行授权逻辑,校验[Authorize]要求 app.UseEndpoints(endpoints => endpoints.MapControllers());
如果顺序颠倒(比如把UseAuthentication放在UseAuthorization之后),或者漏写app.UseAuthentication(),会导致默认Scheme的认证逻辑没有被触发。此时显式在[Authorize]中指定AuthenticationSchemes会强制指定Scheme执行认证逻辑,因此可以正常工作,但依赖默认Scheme的场景会失效。
2. 默认Scheme被其他服务注册覆盖
如果项目同时注册了其他认证类服务(比如ASP.NET Core Identity、Cookie认证、第三方OAuth认证等),这些服务的注册方法(如AddIdentity()、AddCookie())会自动修改全局默认认证Scheme,覆盖你之前在AddAuthentication(JwtBearerDefaults.AuthenticationScheme)中设置的默认值。
比如AddIdentity()会自动将默认认证Scheme设置为Identity专用的Cookie Scheme,此时不显式指定JWT Scheme时,[Authorize]会默认走Cookie认证逻辑,不会校验JWT Token,因此无法生效。
如果存在这类注册,需要在所有认证服务注册完成后,手动重新指定默认Scheme:
services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; });
3. JWT Scheme注册名称与默认配置不匹配
AddAuthentication(JwtBearerDefaults.AuthenticationScheme)传入的参数是默认使用的Scheme名称,这个名称必须和AddJwtBearer()实际注册的Scheme名称完全一致。
如果你调用AddJwtBearer()时手动指定了自定义Scheme名称(例如写成AddJwtBearer("MyCustomJwt", options => ...)),而默认Scheme还是用的默认的Bearer,两者不匹配会导致默认Scheme找不到对应的认证处理器,自然无法生效。
4. 认证选项被后续配置覆盖
如果你在调用AddAuthentication(JwtBearerDefaults.AuthenticationScheme)之后,又重新通过services.AddAuthentication(options => { ... })配置了认证选项,且在这次配置中没有显式设置DefaultAuthenticateScheme,会导致之前设置的默认值被覆盖为空,[Authorize]特性不知道该使用哪个Scheme执行认证。
内容的提问来源于stack exchange,提问作者HamedFathi

