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

如何用.NET JWT中间件同时验证Azure AD令牌与自定义JWT?

我来帮你梳理几个解决这个问题的可行方案,你可以根据自己的实际场景来选:

方案一:配置多个JWT验证方案,允许任一验证通过

你可以通过注册两个独立的JWT Bearer验证方案(分别对应Azure AD和自定义JWT),然后创建一个授权策略,只要其中一个方案验证通过就允许访问。这种方式利用了.NET身份验证系统的原生能力,代码简洁易维护。

具体实现步骤:

  1. 在Startup.cs中注册两个验证方案,并配置对应的验证参数:
var azureAdAuthOptions = new AuthenticationOptions();
configuration.Bind("AzureAd", azureAdAuthOptions);

// 注册Azure AD的JWT验证方案
services.AddAuthentication()
    .AddJwtBearer("AzureADJwt", options => {
        options.Authority = $"{azureAdAuthOptions.Instance}{azureAdAuthOptions.TenantId}";
        options.TokenValidationParameters = new TokenValidationParameters {
            ValidAudience = azureAdAuthOptions.ClientId,
            ValidIssuer = $"{azureAdAuthOptions.Instance}{azureAdAuthOptions.TenantId}/v2.0"
        };
    })
    // 注册自定义JWT的验证方案
    .AddJwtBearer("CustomJwt", options => {
        var mySecret = configuration["CustomJwt:Secret"]; // 生产环境建议从配置读取,不要硬编码
        var mySecurityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(mySecret));
        options.TokenValidationParameters = new TokenValidationParameters {
            ValidAudience = azureAdAuthOptions.ClientId,
            ValidIssuer = $"{azureAdAuthOptions.Instance}{azureAdAuthOptions.TenantId}/v2.0",
            IssuerSigningKey = mySecurityKey,
            ValidateIssuerSigningKey = true
        };
    });

// 创建默认授权策略:允许任一验证方案通过
services.AddAuthorization(options => {
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes("AzureADJwt", "CustomJwt")
        .Build();
});
  1. 之后你现有的[Authorize]标签不需要任何修改,因为我们把这个"二选一"策略设为了全局默认;如果你只想给部分端点用这个规则,也可以创建命名策略,用[Authorize(Policy = "AllowEitherJwt")]指定。

方案二:生成能通过Azure AD验证的自定义令牌?(不可行)

直接生成能通过现有Azure AD验证逻辑的令牌是完全不可能的。Azure AD的令牌是用它自己的私有密钥签名的,这个密钥属于微软Azure的安全体系,你没有任何权限获取或使用。你的自定义令牌没有Azure AD的合法签名,必然会被现有验证逻辑拒绝,所以这个方向不用考虑。


方案三:自定义授权属性,实现"或"逻辑

如果你不想修改全局的验证配置,也可以自定义一个授权处理程序,手动实现"Azure AD验证通过 或 自定义JWT验证通过"的逻辑。

具体实现步骤:

  1. 自定义授权需求和处理程序:
// 定义授权需求
public class EitherAuthorizationRequirement : IAuthorizationRequirement { }

// 实现授权逻辑
public class EitherAuthorizationHandler : AuthorizationHandler<EitherAuthorizationRequirement>
{
    private readonly IAuthenticationService _authenticationService;

    public EitherAuthorizationHandler(IAuthenticationService authenticationService)
    {
        _authenticationService = authenticationService;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, EitherAuthorizationRequirement requirement)
    {
        var httpContext = context.Resource as HttpContext;
        if (httpContext == null)
        {
            context.Fail();
            return;
        }

        // 先尝试Azure AD验证
        var azureAdResult = await _authenticationService.AuthenticateAsync(httpContext, "AzureADJwt");
        if (azureAdResult.Succeeded)
        {
            context.Succeed(requirement);
            return;
        }

        // 再尝试自定义JWT验证
        var customJwtResult = await _authenticationService.AuthenticateAsync(httpContext, "CustomJwt");
        if (customJwtResult.Succeeded)
        {
            context.Succeed(requirement);
            return;
        }

        // 两种验证都失败则拒绝访问
        context.Fail();
    }
}
  1. 在Startup.cs中注册处理程序和对应的策略:
services.AddScoped<IAuthorizationHandler, EitherAuthorizationHandler>();
services.AddAuthorization(options => {
    options.AddPolicy("AllowEitherAuth", policy =>
        policy.Requirements.Add(new EitherAuthorizationRequirement()));
});
  1. 使用时给需要的端点添加标注:[Authorize(Policy = "AllowEitherAuth")]

方案建议

优先选择方案一,因为它完全基于.NET身份验证系统的原生能力,代码最简洁,后续维护成本最低。另外注意:

  • 生产环境中不要硬编码自定义JWT的密钥,建议从配置文件或Azure Key Vault等密钥管理服务读取
  • 自定义JWT的Issuer和Audience要和验证配置完全一致,否则会验证失败

内容的提问来源于stack exchange,提问作者PalBo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:22:31