You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 6中Azure AD与本地认证共存失效问题求助

问题排查与修复方案

核心问题分析

你的代码存在以下几个关键问题,导致两种认证方式均失效:

  1. 自研JWT认证方案(HomebrewScheme)未配置必要的Token验证参数,无法完成token合法性校验
  2. PolicyScheme的转发逻辑错误,仅通过CanReadToken判断会将Azure AD的JWT错误导向未配置的自研方案
  3. 中间件顺序不符合ASP.NET Core认证授权的规范要求
  4. 测试中间件位置错误且未调用next()中断请求流程
  5. 授权策略存在冗余/错误配置

具体修复步骤

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:20:20