C# 自定义授权要求方法 C#如何创建IAuthorizationRequirement和Handler

来源:这里教程网 时间:2026-02-21 17:40:33 作者:

IAuthorizationRequirement 是个空接口,只起标记作用

它本身不带任何逻辑,纯粹用于类型区分——比如你定义

MinimumAgeRequirement
HasPermissionRequirement
,都继承自它,目的是让 Handler 能通过泛型匹配到对应处理逻辑。不要试图在里面加属性或方法来“控制授权流程”,那是 Handler 的事。

常见错误:给 Requirement 加

public bool IsSatisfied { get; set; }
这类运行时状态字段。它会被反复实例化,状态无法保持,也违背了 Requirement 应该是不可变(immutable)设计原则。

正确做法是把必要参数全塞进构造函数,并设为只读:

public class MinimumAgeRequirement : IAuthorizationRequirement
{
    public int MinimumAge { get; }
    public MinimumAgeRequirement(int minimumAge) => MinimumAge = minimumAge;
}

Handler 必须继承 AuthorizationHandler 且重写 HandleRequirementAsync

这是真正干活的地方。ASP.NET Core 在授权时会查找所有注册的

AuthorizationHandler<t></t>
,并把当前
AuthorizationHandlerContext
和匹配的 Requirement 实例传进来。你得在这个方法里决定调用
context.Succeed(requirement)
还是
context.Fail()

关键点:

必须用
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinimumAgeRequirement requirement)
签名,泛型参数 T 必须和你注册的 Requirement 类型一致
不能漏掉
context.Fail()
—— 如果条件不满足又没调用 Fail,授权会“静默通过”(因为默认不失败)
不要在 Handler 里直接 throw 异常,授权失败走
Fail()
,异常留给中间件层处理
如果需要访问用户信息,从
context.User
拿;要读 Claim,别手动遍历,用
context.User.FindFirst("age")?.Value
context.User.HasClaim()

注册 Requirement 和 Handler 要配对,且顺序影响行为

Program.cs
(.NET 6+)中注册时,先用
AddAuthorization
添加策略,再用
AddScoped
注册 Handler。Requirement 不需要单独注册,但策略里要用到它:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("MinimumAge18", policy =>
        policy.Requirements.Add(new MinimumAgeRequirement(18)));
});
builder.Services.AddScoped<IAuthorizationHandler, MinimumAgeHandler>();

注意:

多个 Handler 可以处理同一个 Requirement,它们都会被执行(除非某个调用了
context.Succeed()
后你主动
return
如果一个策略绑了多个 Requirement,所有对应 Handler 都必须成功,策略才算通过 Handler 注册必须是
Scoped
(不是 Singleton),因为
AuthorizationHandlerContext
是每次请求新建的

调试时最常卡在 Handler 没被触发

现象:加了断点但完全不进

HandleRequirementAsync
,策略始终失败。大概率是下面几个原因:

Handler 类型没注册,或者注册成了
AddSingleton
导致依赖注入失败
策略名拼错,比如控制器上写了
[Authorize(Policy = "MinAge18")]
,但注册的是
"MinimumAge18"
Requirement 构造时传参出错,比如
new MinimumAgeRequirement(null)
导致构造函数抛异常,Handler 根本没创建出来
.NET 版本差异:.NET 5+ 要求 Handler 必须实现
IAuthorizationHandler
接口(虽然继承
AuthorizationHandler<t></t>
已隐式实现,但某些反射场景会校验)

建议加一行日志在 Handler 构造函数里,确认它是否被创建;再在

HandleRequirementAsync
开头打日志,看是否进入。比断点更可靠。

Requirement 和 Handler 的耦合其实很轻,但注册链上任意一环断开,整个授权就静默失效——这点最容易被忽略。

相关推荐

热文推荐