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

自定义默认策略下多认证方案的角色授权无法适配所有方案

解决多JWT认证方案下角色授权仅默认方案生效的问题

问题背景

配置了Default和Secondary两个JWT认证方案,通过OnTokenValidated事件为两种Token都添加了Administrator角色。自定义默认认证策略包含这两种方案,无角色要求的接口(如.RequireAuthorization())两种Token均可正常访问,但带角色要求的接口(如.RequireRole("Administrator"))只有DefaultAuthenticateScheme指定的方案Token能通过授权;切换默认方案后,支持的Token也随之反转。非最小API使用[Authorize]或[Authorize(Roles = "Administrator")]时问题完全一致。

问题根源

ASP.NET Core的默认角色授权逻辑(包括RequireRole扩展方法、[Authorize(Roles)]特性)会默认仅使用默认认证方案对应的用户身份来校验角色,哪怕你配置了包含多方案的认证策略,角色校验环节不会自动遍历所有已通过认证的身份信息。

解决方案

方案1:自定义角色授权策略(推荐,灵活可控)

创建一个自定义授权策略,明确要求校验所有已通过认证的身份的角色,而非仅默认方案的身份。

步骤1:配置自定义策略

在Program.cs的授权配置中添加自定义策略:

builder.Services.AddAuthorization(options =>
{
    // 保留原有的默认认证策略,支持两种方案的身份认证
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes("Default", "Secondary")
        .RequireAuthenticatedUser()
        .Build();

    // 自定义支持多方案的角色策略
    options.AddPolicy("MultiSchemeAdministrator", policy =>
    {
        policy.AddAuthenticationSchemes("Default", "Secondary");
        policy.RequireAssertion(context =>
        {
            // 遍历所有已认证的身份,检查是否存在包含目标角色的身份
            return context.User.Identities.Any(identity => 
                identity.IsAuthenticated && 
                identity.HasClaim(c => c.Type == ClaimTypes.Role && c.Value == "Administrator"));
        });
    });
});

步骤2:接口绑定自定义策略

  • 最小API场景:
    app.MapGet("/two", () => "Access granted for /two")
       .RequireAuthorization("MultiSchemeAdministrator");
    
  • MVC/API控制器场景:
    [Authorize(Policy = "MultiSchemeAdministrator")]
    public IActionResult Two()
    {
        return Ok("Access granted for /two");
    }
    

方案2:全局替换默认角色授权处理器

如果希望保留原有的RequireRole或[Authorize(Roles)]用法,无需每个接口指定自定义策略,可以替换默认的角色授权处理器,让它支持多认证方案:

步骤1:实现自定义授权处理器

public class MultiSchemeRoleAuthorizationHandler : AuthorizationHandler<RolesAuthorizationRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RolesAuthorizationRequirement requirement)
    {
        // 检查所有已认证的身份中,是否有任意一个包含要求的角色
        var hasValidRole = context.User.Identities
            .Where(identity => identity.IsAuthenticated)
            .Any(identity => requirement.AllowedRoles.Any(role => identity.HasClaim(ClaimTypes.Role, role)));

        if (hasValidRole)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

步骤2:注册自定义处理器

在Program.cs中添加服务注册:

builder.Services.AddSingleton<IAuthorizationHandler, MultiSchemeRoleAuthorizationHandler>();

配置完成后,原有的.RequireRole("Administrator")或[Authorize(Roles = "Administrator")]就能自动支持两种认证方案的Token了。

关键验证点

确保两个JWT认证方案的OnTokenValidated事件都正确添加了角色声明,示例如下:

// 配置Default方案时的事件
options.Events = new JwtBearerEvents
{
    OnTokenValidated = context =>
    {
        if (context.Principal?.Identity is ClaimsIdentity claimsIdentity)
        {
            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "Administrator"));
        }
        return Task.CompletedTask;
    }
};

// 配置Secondary方案时同样要添加该事件逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 19:01:30