ASP.NET Core 6中Azure AD与本地认证共存失效问题求助
问题排查与修复方案
核心问题分析
你的代码存在以下几个关键问题,导致两种认证方式均失效:
- 自研JWT认证方案(
HomebrewScheme)未配置必要的Token验证参数,无法完成token合法性校验 - PolicyScheme的转发逻辑错误,仅通过
CanReadToken判断会将Azure AD的JWT错误导向未配置的自研方案 - 中间件顺序不符合ASP.NET Core认证授权的规范要求
- 测试中间件位置错误且未调用
next()中断请求流程 - 授权策略存在冗余/错误配置
具体修复步骤
1. 完善自研JWT认证配置
必须为HomebrewScheme添加Token验证参数,否则无法通过认证:
.AddJwtBearer("HomebrewScheme", options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = "你的自研JWT发行者地址", // 例如:https://your-domain.com/auth ValidateAudience = true, ValidAudience = "你的API受众标识", // 例如:api://your-api-id ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("你的JWT签名密钥")), ValidateLifetime = true // 可选:开启过期时间验证 }; })
2. 修正PolicyScheme转发逻辑
通过解析JWT的Issuer字段区分两种认证方案,替代原有的CanReadToken判断:
.AddPolicyScheme("MultiAuthSchemes", "Multi Authentication Scheme", options => { options.ForwardDefaultSelector = context => { string authorization = context.Request.Headers[HeaderNames.Authorization]; if (!string.IsNullOrEmpty(authorization) && authorization.StartsWith("Bearer ")) { var token = authorization["Bearer ".Length..].Trim(); var jwtHandler = new JwtSecurityTokenHandler(); if (jwtHandler.CanReadToken(token)) { var jwtToken = jwtHandler.ReadJwtToken(token); // 根据发行者区分方案 if (jwtToken.Issuer == "你的自研JWT发行者地址") { return "HomebrewScheme"; } // Azure AD发行者格式通常为 https://login.microsoftonline.com/{tenantId}/v2.0 else if (jwtToken.Issuer.StartsWith("https://login.microsoftonline.com/")) { return "AdScheme"; } } } // 无Bearer Token时使用Cookie认证 return CookieAuthenticationDefaults.AuthenticationScheme; }; })
3. 调整中间件顺序(关键)
ASP.NET Core认证授权的正确顺序为:UseRouting → UseAuthentication → UseAuthorization,同时将测试中间件移至认证授权之后:
app.UseGraphQLPlayground(new PlaygroundOptions { GraphQLEndPoint = GraphQLApiEndpoint }); app.UseWebSockets(); app.UseRouting(); // 认证中间件必须在路由之后、授权之前 app.UseAuthentication(); app.UseAuthorization(); // 测试中间件移至认证授权之后,且必须调用next() app.Use((context, next) => { if (context.User.Identity?.IsAuthenticated == true) { PermissionLevel = Permissions.Authorized; } return next(); // 必须调用,否则请求会被中断 }); app.UseEndpoints(x => x.MapGraphQL(path: GraphQLApiEndpoint));
4. 修复授权策略错误
移除冗余的空AddAuthenticationSchemes()调用,简化默认策略配置:
services.AddAuthorization(o => { // 默认策略支持所有认证方案 var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder( CookieAuthenticationDefaults.AuthenticationScheme, "HomebrewScheme", "AdScheme"); o.DefaultPolicy = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser().Build(); // 仅自研JWT的策略 o.AddPolicy("OnlyHomebrewScheme", new AuthorizationPolicyBuilder("HomebrewScheme") .RequireAuthenticatedUser() .Build()); // 仅Azure AD的策略 o.AddPolicy("OnlyAdScheme", new AuthorizationPolicyBuilder("AdScheme") .RequireAuthenticatedUser() .Build()); });
5. 额外检查项
- 确认
appsettings.json中的Azure AD配置(AzureAd节点)包含正确的Instance、TenantId、ClientId和Audience - 如果
services.AddJwtAuthorization();是第三方库方法,确认其不会与自定义认证配置冲突,必要时可暂时移除测试
内容的提问来源于stack exchange,提问作者Belle 'Sandon' Ling
相关产品推荐
相关产品推荐

