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

如何在ASP.NET Core 3.1 API中配置多授权方式?

问题描述

我运行着一个基于ASP.NET Core 3.1的API,当前使用JWT Bearer令牌(由OAuth2提供商颁发)正常工作,默认授权策略已配置并启用RequireAuthenticatedUser()。现在需要给部分端点配置另一种授权流程,于是创建了自定义AuthorizationHandler并绑定到对应策略,绑定到目标端点后,自定义Handler确实触发了,而且已经调用context.Succeed(requirement)并返回Task.CompletedTask,但仍然收到401未授权响应,求排查问题。

自定义Handler代码:

public class MyCustomAuthorizeRequirement : IAuthorizationRequirement
{ }

public class MyCustomAuthorizeRequirementHandler : AuthorizationHandler<MyCustomAuthorizeRequirement>, IAuthorizationRequirement
{
    private readonly MyCustomSettings _MyCustomSettings;
    public MyCustomAuthorizeRequirementHandler(MyCustomSettings MyCustomSettings)
    {
        _MyCustomSettings = MyCustomSettings;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyCustomAuthorizeRequirement requirement)
    {
        var httpContext = context.Resource as HttpContext;

        string authHeader = httpContext.Request.Headers["Authorization"];

        if (authHeader != null && authHeader.StartsWith("x-auth-"))
        {
            if(authHeader != _MyCustomSettings.MyCustomAuthKey)
            {
                context.Fail();
                return Task.CompletedTask;
            }
        }

        context.Succeed(requirement);
        return Task.CompletedTask;
    }
}

Program.cs相关代码片段:

builder.Services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer();

    // Configure policies
    builder.Services
        .AddAuthorization(options =>
        {
            var userAuthPolicyBuilder = new AuthorizationPolicyBuilder();
            options.DefaultPolicy = userAuthPolicyBuilder
                .RequireAuthenticatedUser()
                .Build();

            
            options.AddPolicy("MyCustomAuthorize", policy => policy.Requirements.Add(new MyCustomAuthorizeRequirement()));
        });

    MyCustomSettings localMyCustomSettings = new MyCustomSettings();
    configuration.GetSection("MyCustomSettings").Bind(localMyCustomSettings);
    builder.Services.AddSingleton<IAuthorizationHandler>(new MyCustomAuthorizeRequirementHandler(localMyCustomSettings));

问题排查与修复

1. 自定义Handler错误实现IAuthorizationRequirement

MyCustomAuthorizeRequirementHandler同时继承AuthorizationHandler<MyCustomAuthorizeRequirement>和实现IAuthorizationRequirement是错误的。IAuthorizationRequirement是授权要求的标记接口,Handler是处理要求的逻辑类,不需要实现该接口。这个错误会让授权系统把Handler当成额外的未处理要求,最终导致授权失败。

2. 自定义策略未脱离默认认证约束

默认策略要求RequireAuthenticatedUser(),但自定义策略仅添加了自定义要求,未明确跳过默认的JWT认证检查。当请求使用自定义x-auth-头时,JWT认证中间件会因找不到有效令牌标记用户为未认证,即便自定义Handler通过,最终仍会因默认认证要求未满足返回401。

3. 自定义Handler逻辑存在漏洞

当前逻辑中,若Authorization头不以x-auth-开头,会直接调用context.Succeed(requirement),导致未携带正确头的请求也能通过自定义策略,但结合默认认证仍会失败;同时需明确所有分支的授权结果,避免逻辑遗漏。


修改后的代码示例

修正自定义Handler

public class MyCustomAuthorizeRequirement : IAuthorizationRequirement
{ }

// 移除IAuthorizationRequirement接口实现
public class MyCustomAuthorizeRequirementHandler : AuthorizationHandler<MyCustomAuthorizeRequirement>
{
    private readonly MyCustomSettings _myCustomSettings;
    public MyCustomAuthorizeRequirementHandler(MyCustomSettings myCustomSettings)
    {
        _myCustomSettings = myCustomSettings;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyCustomAuthorizeRequirement requirement)
    {
        var httpContext = context.Resource as HttpContext;
        string authHeader = httpContext.Request.Headers["Authorization"];

        if (authHeader != null && authHeader.StartsWith("x-auth-"))
        {
            if (authHeader == _myCustomSettings.MyCustomAuthKey)
            {
                context.Succeed(requirement);
                return Task.CompletedTask;
            }
            context.Fail();
            return Task.CompletedTask;
        }

        // 未携带正确自定义头,直接拒绝
        context.Fail();
        return Task.CompletedTask;
    }
}

修正Program.cs授权策略配置

builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer();

// 配置授权策略
builder.Services
    .AddAuthorization(options =>
    {
        // 默认策略:要求JWT认证
        options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
            .RequireAuthenticatedUser()
            .Build();

        // 自定义策略:仅使用自定义授权逻辑,不依赖默认认证要求
        options.AddPolicy("MyCustomAuthorize", policy =>
        {
            policy.Requirements.Add(new MyCustomAuthorizeRequirement());
        });
    });

// 注册自定义Handler(泛型方式更简洁)
MyCustomSettings localMyCustomSettings = new MyCustomSettings();
configuration.GetSection("MyCustomSettings").Bind(localMyCustomSettings);
builder.Services.AddSingleton<IAuthorizationHandler, MyCustomAuthorizeRequirementHandler>(sp => 
    new MyCustomAuthorizeRequirementHandler(localMyCustomSettings));

端点绑定自定义策略

确保目标端点使用自定义策略,而非默认授权:

[ApiController]
[Route("api/custom")]
public class CustomController : ControllerBase
{
    [HttpGet]
    [Authorize(Policy = "MyCustomAuthorize")]
    public IActionResult Get()
    {
        return Ok("Custom authorized access");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 12:40:50