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

.NET Core如何通过Attribute为Authorization Handler提供实例?

在.NET中通过[Authorize]属性注入自定义授权接口实例的实现方案

完全可以通过自定义[Authorize]属性结合DI容器来实现每个端点的个性化授权逻辑,以下是具体落地步骤:

1. 定义端点授权检查接口

先抽象出所有个性化授权逻辑需要实现的统一接口:

public interface IEndpointAuthorizationChecker
{
    Task<bool> CheckAuthorizationAsync(AuthorizationHandlerContext context);
}

2. 自定义Authorize属性

扩展原生AuthorizeAttribute,添加属性指定当前端点要使用的授权检查实现类:

public class AuthorizeWithCheckerAttribute : AuthorizeAttribute
{
    public Type CheckerType { get; }

    public AuthorizeWithCheckerAttribute(Type checkerType)
    {
        if (!typeof(IEndpointAuthorizationChecker).IsAssignableFrom(checkerType))
        {
            throw new ArgumentException("指定的检查器类型必须实现IEndpointAuthorizationChecker接口");
        }
        CheckerType = checkerType;
        // 用检查器类型全名作为策略名称,确保每个检查器对应唯一策略
        Policy = checkerType.FullName;
    }
}

3. 自定义PolicyProvider

重写DefaultAuthorizationPolicyProvider,根据策略名称(检查器类型全名)生成对应授权策略:

public class CheckerBasedPolicyProvider : DefaultAuthorizationPolicyProvider
{
    public CheckerBasedPolicyProvider(IOptions<AuthorizationOptions> options) : base(options)
    {
    }

    public override async Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        // 优先获取原生策略
        var policy = await base.GetPolicyAsync(policyName);
        if (policy != null)
            return policy;

        // 根据检查器类型创建自定义策略
        var checkerType = Type.GetType(policyName);
        if (checkerType != null && typeof(IEndpointAuthorizationChecker).IsAssignableFrom(checkerType))
        {
            var policyBuilder = new AuthorizationPolicyBuilder();
            policyBuilder.AddRequirements(new CheckerAuthorizationRequirement(checkerType));
            return policyBuilder.Build();
        }

        return null;
    }
}

// 自定义授权要求,用于携带检查器类型
public class CheckerAuthorizationRequirement : IAuthorizationRequirement
{
    public Type CheckerType { get; }

    public CheckerAuthorizationRequirement(Type checkerType)
    {
        CheckerType = checkerType;
    }
}

4. 实现自定义AuthorizationHandler

在Handler中从DI容器获取对应检查器实例,执行授权检查:

public class CheckerAuthorizationHandler : AuthorizationHandler<CheckerAuthorizationRequirement>
{
    private readonly IServiceProvider _serviceProvider;

    public CheckerAuthorizationHandler(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, CheckerAuthorizationRequirement requirement)
    {
        // 从DI获取检查器实例
        if (_serviceProvider.GetService(requirement.CheckerType) is IEndpointAuthorizationChecker checker)
        {
            var result = await checker.CheckAuthorizationAsync(context);
            if (result)
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
        }
        else
        {
            // 找不到检查器实例,直接拒绝授权
            context.Fail();
        }
    }
}

5. 注册服务到DI容器

在Program.cs中完成服务注册:

builder.Services.AddAuthorization();

// 替换默认的PolicyProvider
builder.Services.AddSingleton<IAuthorizationPolicyProvider, CheckerBasedPolicyProvider>();
// 注册自定义Handler
builder.Services.AddSingleton<IAuthorizationHandler, CheckerAuthorizationHandler>();

// 注册具体的端点授权检查器示例
builder.Services.AddScoped<IEndpointAuthorizationChecker, OrderEndpointChecker>();
builder.Services.AddScoped<IEndpointAuthorizationChecker, UserEndpointChecker>();

6. 在端点上使用自定义属性

在Controller Action或Minimal API端点上直接标记:

[ApiController]
[Route("api/orders")]
public class OrdersController : ControllerBase
{
    [HttpGet]
    [AuthorizeWithChecker(typeof(OrderEndpointChecker))]
    public IActionResult GetOrders()
    {
        // 业务逻辑
        return Ok();
    }
}

// 示例检查器实现
public class OrderEndpointChecker : IEndpointAuthorizationChecker
{
    private readonly IUserService _userService;

    public OrderEndpointChecker(IUserService userService)
    {
        _userService = userService;
    }

    public async Task<bool> CheckAuthorizationAsync(AuthorizationHandlerContext context)
    {
        // 编写该端点的个性化授权逻辑
        var userId = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        return await _userService.HasOrderAccessAsync(userId);
    }
}

注意事项

  • 所有检查器实现类必须注册到DI容器,否则Handler无法获取实例
  • Minimal API中使用方式:
    app.MapGet("/api/users", () => Results.Ok())
       .RequireAuthorization(new AuthorizeWithCheckerAttribute(typeof(UserEndpointChecker)));
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 02:47:41