C# 自定义授权要求方法 C#如何创建IAuthorizationRequirement和Handler
发布时间 - 2026-02-02 00:00:00 点击率:次IAuthorizationRequirement是仅用于类型标记的空接口,要求不可变且通过构造函数传参;Handler必须继承AuthorizationHandler并重写HandleRequirementAsync,注册需为Scoped且策略名、类型、参数须完全匹配。
IAuthorizationRequirement 是个空接口,只起标记作用
它本身不带任何逻辑,纯粹用于类型区分——比如你定义 MinimumAgeRequirement 或 HasPermissionRequirement,都继承自它,目的是让 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,并把当前 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();
注意:
- 多个 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 已隐式实现,但某些反射场景会校验)
建议加一行日志在 Handler 构造函数里,确认它是否被创建;再在 HandleRequirementAsync 开头打日志,看是否进入。比断点更可靠。
Requirement 和 Handler 的耦合其实很轻,但注册链上任意一环断开,整个授权就静默失效——这点最容易被忽略。
这是真正干活的地方。ASP.NET Core 在授权时会查找所有注册的 AuthorizationHandler,并把当前 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();
注意:
- 多个 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已隐式实现,但某些反射场景会校验)
建议加一行日志在 Handler 构造函数里,确认它是否被创建;再在 HandleRequirementAsync 开头打日志,看是否进入。比断点更可靠。
Requirement 和 Handler 的耦合其实很轻,但注册链上任意一环断开,整个授权就静默失效——这点最容易被忽略。
# ai
# c#
# .net
# 中间件
# NULL
# 构造函数
# throw
# bool
# 继承
# 接口
# public
# protected
# 泛型
# 多个
# 重写
# 的是
# 这是
# 几个
# 是个
# 成了
# 在这个
# 那是
# 不需要
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】
HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】
HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】
Python3.6正式版新特性预览
东莞市网站制作公司有哪些,东莞找工作用什么网站好?
Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制
b2c电商网站制作流程,b2c水平综合的电商平台?
Laravel如何升级到最新版本?(升级指南和步骤)
如何快速打造个性化非模板自助建站?
怎么用AI帮你为初创公司进行市场定位分析?
Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】
C++时间戳转换成日期时间的步骤和示例代码
EditPlus中的正则表达式实战(6)
Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】
Laravel怎么创建自己的包(Package)_Laravel扩展包开发入门到发布
Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】
Laravel如何使用查询构建器?(Query Builder高级用法)
Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
如何生成腾讯云建站专用兑换码?
Edge浏览器如何截图和滚动截图_微软Edge网页捕获功能使用教程【技巧】
弹幕视频网站制作教程下载,弹幕视频网站是什么意思?
Python文件操作最佳实践_稳定性说明【指导】
如何登录建站主机?访问步骤全解析
Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
打造顶配客厅影院,这份100寸电视推荐名单请查收
如何快速生成可下载的建站源码工具?
如何在阿里云通过域名搭建网站?
网站优化排名时,需要考虑哪些问题呢?
如何为不同团队 ID 动态生成多个非值班状态按钮
儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?
如何正确下载安装西数主机建站助手?
如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】
如何获取上海专业网站定制建站电话?
Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程
Linux后台任务运行方法_nohup与&使用技巧【技巧】
Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
SQL查询语句优化的实用方法总结
如何实现建站之星域名转发设置?
如何在新浪SAE免费搭建个人博客?
Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】
美食网站链接制作教程视频,哪个教做美食的网站比较专业点?
Laravel怎么多语言本地化设置_Laravel语言包翻译与Locale动态切换【手册】
Laravel如何创建和注册中间件_Laravel中间件编写与应用流程
今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】
详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)

