代码基于微软官方案例.
1、先了解几个关键的类,不要怕看到一知半解,后面结合案例马上明了。
策略(Policy):没有这个类。含义其实和我们生活中所说的“策略”含义差不多。一套系统中,可能有多种权限验证。我们给每一种权限验证定义一个名称,某某策略。比如有验证用户年龄的,到达年龄才能买酒。有验证地区的,北京用户买菜刀要实名。那么我们就可以叫他们年龄策略,地区策略。
IAuthorizationRequirement:官方原话“是一项没有方法的标记服务以及用于跟踪授权是否成功的机制。”自己理解:再配置策略时,配置的一个对象,实现对Handler传参。同时也是根据这个Requirement(要求),找到处理这个要求的Handler。
IAuthorizationHandler:官方原话:“负责检查是否满足要求。”自己理解:就是写验证业务的类要继承这个接口。一般我们继承AuthorizationHandler<TRequirement>,看到泛型TRequirement了么,继承自上面的IAuthorizationRequirement。这里我们就看到Handler和Requirement的绑定关系了。 通过策略配置的要求(Requirement)找到处理要求的Handler
AuthorizationHandlerContext 官方原话:“是处理程序(Handler)用来标记是否满足要求的类。”自己理解:是通过验证了,还是没通过验证,用这个对象标记。当然还有一些其他信息可以从上下文(Context)中拿到,比如当前用户信息。
AuthorizeAttribute:官方原话:“指定此属性应用于的类或方法需要指定的授权。”自己理解:用这个特性描述的controller,action会进行相应权限验证。
为啥我要把官方原话和自己的理解都写上呢,是想体会官方表达和自己表达的差异。
2、这几个类是怎么组织起来的呢?
通过官方案例我们分析下,源码在这。
这个案例需要你会点EF Core知识,以及身份验证知识。官方案例运行起来需要先注册,注册后需要邮箱验证,可以吧options.SignIn.RequireConfirmedAccount改成false,这样用户注册之后就可以直接登陆了,不需要邮箱认证。
案例定义了“AtLeast21”这样一个最小21岁的策略。
2.1、先定义这个策略有什么要求,MinimumAgeRequirement类,可以指定最小年龄MinimumAge。验证时会将Requirement实例传入到handler。
2.2、处理这个要求的Handler,MinimumAgeHandler类,继承自AuthorizationHandler<MinimumAgeRequirement>。HandleRequirementAsync函数用于实际处理验证逻辑。context.User:从上下文中获取到当前用户信息。
如果通过验证,则Handler 会调用 context.Succeed。 授权处理程序通常:
- 满足要求时调用 context.Succeed。
- 未满足要求时返回 Task.CompletedTask。 在未事先调用 context.Success 或 context.Fail 的情况下返回 Task.CompletedTask 不是成功或失败,它允许运行其他授权处理程序。
- 如果需要显式失败,请调用 context.Fail。
2.3、在启动类中,启用身份验证
app.UseAuthorization()
然后配置策略、注意配置策略的时候,指定哪个策略,指定相应的要求(Requirement)
services.AddAuthorization(options =>
{
options.AddPolicy("AtLeast21", policy =>
{
policy.Requirements.Add(new MinimumAgeRequirement(21));
});
});
注册Handler
services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
2.4、最后,你需要告诉哪个controller或action需要授权,在上面加上[Authorize(policy: "AtLeast21")]就完成了。
/// <summary>
/// </summary>
[Authorize(Policy = "AtLeast21")]
public class AlcoholPurchaseController : Controller
{
public IActionResult Index() => View();
}