ASP.NET Core API(v2.1)多认证方案仅默认Schema生效问题排查
解决ASP.NET Core 2.1多JWT认证仅默认Scheme生效的问题
看起来你遇到的是多JWT认证场景下的常见误区——默认的认证与授权逻辑并不会自动支持「任意一个Scheme通过即可」的需求,这里有两个关键配置被你忽略了,咱们一步步来解决:
问题根源拆解
1. 授权策略默认是「AND」逻辑
你当前的授权策略代码:
options.DefaultPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme, OtherSchema) .RequireAuthenticatedUser() .Build();
这段代码的实际含义是:用户必须同时通过两个Scheme的认证才能访问接口,而不是通过其中一个就行。这也是为什么只有默认Scheme的令牌能通过——另一个Scheme的认证根本没触发,自然满足不了「双Scheme都通过」的要求。
2. 认证中间件只会使用默认Scheme验证令牌
你在AddAuthentication中指定了默认Scheme为JwtBearerDefaults.AuthenticationScheme,所以认证中间件只会用这个Scheme的配置去解析令牌,完全不会尝试MyOtherSchema的验证规则。哪怕交换AddJwtBearer的顺序,默认Scheme还是第一个,结果当然不会改变。
完整解决方案
我们需要同时调整认证和授权配置,让系统能根据令牌特征选择对应Scheme验证,并且授权时允许任意一个Scheme通过:
1. 配置PolicyScheme作为默认认证入口,动态选择验证Scheme
把默认认证Scheme替换为自定义的PolicyScheme,让它根据令牌的Issuer(或其他Claims)动态选择对应的JWT验证规则:
public void ConfigureServices(IServiceCollection services) { const string OtherSchema = "MyOtherSchema"; const string MultiJwtScheme = "MultiJwtScheme"; // 自定义PolicyScheme名称 services.AddAuthentication(MultiJwtScheme) // 添加PolicyScheme作为默认认证入口 .AddPolicyScheme(MultiJwtScheme, "Multiple JWT Authentication", options => { options.ForwardDefaultSelector = context => { // 从请求头提取Bearer令牌 var authHeader = context.Request.Headers["Authorization"].FirstOrDefault(); if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ")) { return JwtBearerDefaults.AuthenticationScheme; } var token = authHeader.Substring(7); var jwtHandler = new JwtSecurityTokenHandler(); if (jwtHandler.CanReadToken(token)) { var jwtToken = jwtHandler.ReadJwtToken(token); // 根据令牌的Issuer选择对应的验证Scheme // 替换为你两个JWT的实际Issuer地址 if (jwtToken.Issuer == "https://your-first-issuer.com") { return JwtBearerDefaults.AuthenticationScheme; } else if (jwtToken.Issuer == "https://your-second-issuer.com") { return OtherSchema; } } // 默认返回第一个Scheme return JwtBearerDefaults.AuthenticationScheme; }; }) // 第一个JWT Scheme配置 .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { options.TokenValidationParameters = GetFirstTokenValidationParameters(); }) // 第二个JWT Scheme配置 .AddJwtBearer(OtherSchema, options => { options.TokenValidationParameters = GetSecondTokenValidationParameters(); });
2. 修改授权策略为「OR」逻辑,允许任意一个Scheme通过
调整授权规则,只要用户通过任意一个指定Scheme的认证即可访问接口:
services.AddAuthorization(options => { options.DefaultPolicy = new AuthorizationPolicyBuilder() .RequireAssertion(context => // 检查用户是否持有任意一个Scheme的认证身份 context.User.Identities.Any(identity => identity.AuthenticationType == JwtBearerDefaults.AuthenticationScheme || identity.AuthenticationType == OtherSchema)) .Build(); });
额外说明
- 如果你的两个JWT没有Issuer区分(比如Issuer相同但Audience不同),也可以根据
Audience或其他自定义Claims来判断选择哪个Scheme。 - 若不想做动态判断,也可以自定义认证Handler让系统依次尝试所有Scheme,但动态选择的方式性能更优。
这样配置后,不管是默认Scheme的令牌还是MyOtherSchema的令牌,都会被对应的规则正确验证,并且只要通过其中一个就能完成授权。
内容的提问来源于stack exchange,提问作者Saeid
相关产品推荐
相关产品推荐

