自定义授权要求
构建自定义要求和处理程序。
自定义授权要求 是 CoddyKit 上的免费 C# Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。
内置功能不足以应对时
有些规则无法通过 RequireRole 或 RequireClaim 表达——例如“年龄必须至少为 18 岁”或“必须拥有此资源”。
对于这些规则,您需要编写自定义要求和处理程序。
// Rule: user must be older than a configurable minimum ageIAuthorizationRequirement
要求是一种携带规则数据的标记。它实现了空的 IAuthorizationRequirement 接口。
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public int MinimumAge { get; }
public MinimumAgeRequirement(int minimumAge) =>
MinimumAge = minimumAge;
}AuthorizationHandler
处理程序包含逻辑。请从 AuthorizationHandler<TRequirement> 派生,并重写 HandleRequirementAsync。
public class MinimumAgeHandler
: AuthorizationHandler<MinimumAgeRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
MinimumAgeRequirement requirement)
{
// logic goes here
return Task.CompletedTask;
}
}使要求成功
在处理程序内部检查用户的声明。如果满足规则,请调用 context.Succeed(requirement)。如果不满足,只需直接返回,不要调用它。
var dobClaim = context.User.FindFirst("birthdate");
if (dobClaim is null) return Task.CompletedTask;
var dob = DateTime.Parse(dobClaim.Value);
int age = DateTime.UtcNow.Year - dob.Year;
if (dob > DateTime.UtcNow.AddYears(-age)) age--;
if (age >= requirement.MinimumAge)
context.Succeed(requirement);
return Task.CompletedTask;调用 Succeed,而不是 Fail
满足要求时,优先调用 Succeed,否则不执行任何操作。只有当您希望无论同一要求的其他处理程序如何处理都确保失败时,才调用 context.Fail()。
// Soft: let other handlers also try
if (ok) context.Succeed(requirement);
// Hard: force failure no matter what
if (blocked) context.Fail();注册处理程序
将处理程序作为 IAuthorizationHandler 注册到 DI 中。除非处理程序依赖作用域服务,否则通常应将其注册为单例。
builder.Services.AddSingleton<
IAuthorizationHandler, MinimumAgeHandler>();附加到策略
使用 AddRequirements(或 Requirements.Add)将要求添加到命名策略。系统会根据类型自动匹配处理程序。
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast18", policy =>
policy.AddRequirements(new MinimumAgeRequirement(18)));
});使用策略
像使用其他命名策略一样应用它。
[Authorize(Policy = "AtLeast18")]
[HttpGet("age-restricted")]
public IActionResult Restricted() => Ok();基于资源的授权
如果要针对特定实例进行授权(例如“只有文档所有者可以编辑”),请使用资源重载。资源会传入处理程序上下文。
public class OwnerHandler
: AuthorizationHandler<OwnerRequirement, Document>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
OwnerRequirement requirement,
Document resource)
{
var userId = context.User.FindFirstValue(
ClaimTypes.NameIdentifier);
if (resource.OwnerId.ToString() == userId)
context.Succeed(requirement);
return Task.CompletedTask;
}
}调用 IAuthorizationService
基于资源的检查会在操作内部通过注入的 IAuthorizationService 以命令式方式运行。
public async Task<IActionResult> Edit(int id)
{
var doc = await _db.Documents.FindAsync(id);
var result = await _authz.AuthorizeAsync(
User, doc, "DocumentOwner");
if (!result.Succeeded) return Forbid();
return Ok(doc);
}一个要求对应多个处理程序
一个要求可以拥有多个处理程序;只要任意一个处理程序成功,该要求就满足了。这样可以清晰地表示 OR 条件(除非某个处理程序调用了 Fail)。
// e.g. allow if owner OR if admin role
services.AddSingleton<IAuthorizationHandler, OwnerHandler>();
services.AddSingleton<IAuthorizationHandler, AdminOverrideHandler>();快速检查
测试您对处理程序的理解。
回顾
您构建了自定义授权:
IAuthorizationRequirement保存规则数据。AuthorizationHandler<T>包含逻辑并调用Succeed。- 将处理程序注册为
IAuthorizationHandler,并将要求附加到策略。 - 基于资源的处理程序和
IAuthorizationService可以针对特定实例执行授权。
授权课程到此完成。
常见问题解答
「自定义授权要求」课时是免费的吗?
是的 — 「自定义授权要求」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。
「自定义授权要求」这节课中我会学到什么?
构建自定义要求和处理程序。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C# Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「自定义授权要求」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C# Academy 课中编写并运行代码吗?
能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。