.NET Core 6如何取消JWT Bearer令牌强制校验 支持API Key认证
问题根源
你当前将JWT Bearer设为全局唯一的默认认证、质询方案,认证管道默认要求所有请求必须通过JWT合法性校验,只要请求头未携带合法Bearer令牌,就会直接返回401响应,不会进入你自定义的API Key校验逻辑。
最小改动解决方案
不需要重构现有代码,只需要两步调整即可实现JWT、API Key两种认证方式共存,不强制要求请求携带Bearer令牌:
- 调整JWT Bearer的事件配置,让它在检测到请求没有携带Bearer格式令牌时,直接跳过JWT校验,把认证权限交给后续管道处理
- 修正中间件管道顺序,确保API Key校验逻辑在授权中间件执行前完成,校验通过后主动标记请求为已认证状态
第一步:修改JWT认证配置
在你原有AddJwtBearer代码中新增事件配置,修改后完整代码如下:
services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, ValidateIssuer = true, ValidateAudience = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.Secret)), ValidIssuer = jwtSettings.Issuer, ValidAudiences = jwtSettings.Audiences, ClockSkew = TimeSpan.Zero }; // 新增以下事件逻辑 options.Events = new JwtBearerEvents { OnMessageReceived = context => { var authHeader = context.Request.Headers.Authorization.FirstOrDefault(); // 未携带Bearer格式令牌时,跳过JWT校验,不直接返回401 if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { context.NoResult(); return Task.CompletedTask; } return Task.CompletedTask; } }; });
第二步:调整中间件顺序+补全API Key中间件逻辑
必须严格按照以下顺序排列中间件,否则逻辑不会生效:
app.UseRouting(); // 1. 先跑JWT认证中间件 app.UseAuthentication(); // 2. 再跑你自定义的API Key校验中间件 app.UseMiddleware<YourCustomApiKeyMiddleware>(); // 3. 最后跑授权中间件 app.UseAuthorization(); // 端点映射配置 app.MapControllers();
同时需要在你的自定义API Key中间件中补全认证标记逻辑:
- 当从请求头中获取到合法API Key时,构造包含对应身份信息的
ClaimsPrincipal对象,赋值给context.User - 调用
await next()传递给后续管道,此时授权中间件会识别到请求已认证,不会返回401 - 如果API Key校验不通过,再直接返回401响应即可
可选优化(更规范的实现)
如果不想用自定义中间件,可以将API Key校验逻辑封装为独立的认证方案(继承AuthenticationHandler<AuthenticationSchemeOptions>实现),注册后通过[Authorize]特性指定支持的认证方案,即可实现两种认证方式自动 fallback,不需要手动处理管道传递逻辑,适合后续认证逻辑扩展。
内容的提问来源于stack exchange,提问作者Kien D
相关产品推荐
相关产品推荐

