ASP.NET Core 6.0 添加 JWT 认证和授权( 三 )


建议看一下ASP.NET Core 认证与授权6:授权策略是怎么执行的?这篇文章,文章将授权相关的源码整理出来了,并说明了其中的关系 。
这里简单梳理一下:
与授权相关的 interface 和 class 如下:
IAuthorizationService #验证授权的服务,主要方法AuthorizeAsyncDefaultAuthorizationService #IAuthorizationService的默认实现IAuthorizationHandler #负责检查是否满足要求,主要方法HandleAsyncIAuthorizationRequirement #只有属性,没有方法;用于标记服务,以及用于追踪授权是否成功的机制 。AuthorizationHandler<TRequirement> #主要方法HandleRequirementAsync这些 interface 和 class 的关系以及授权过程是这样的:
DefaultAuthorizationService 实现 IAuthorizationService 的 AuthorizeAsync 方法 。
AuthorizeAsync 方法会获取到所有实现了 IAuthorizationHandler 的实例,并循环调用所有实例的 HandleAsync 方法检查是否满足授权要求,如果有任一一个 HandleAsync 返回了 Fail 则将结束循环(细节请参考官方文档处理程序返回结果),并禁止用户访问 。
IAuthorizationHandler 的作用如上一点所述,提供了一个 HandleAsync 方法,用于检查授权 。
IAuthorizationRequirement 是一个要求,主要是配合 AuthorizationHandler<TRequirement> 使用 。
AuthorizationHandler<TRequirement> 实现了 IAuthorizationHandler 的 HandleAsync 方法,并提供了一个 HandleRequirementAsync 的方法 。HandleRequirementAsync 用于检查 Requirement(要求)是否满足 。HandleAsync 的默认实现为获取所有实现 TRequirement 的请求(且该请求由 Policy 添加进列表里),循环调用 HandleRequirementAsync,检查哪个要求(Requirement)能满足授权 。
简述一下:
[Authorize] 标签生效时,调用的是 IAuthorizationService 的 AuthorizeAsync(由 DefaultAuthorizationService 实现) 。
AuthorizeAsync 会去调用所有 IAuthorizationHandler 的 HandleAsync (由 AuthorizationHandler<TRequirement> 实现) 。
HandleAsync 会去调用 AuthorizationHandler<TRequirement> 的HandleRequirementAsync 的方法 。
注意:这里只是列出了主要的接口和类,部分没有列出,如:IAuthorizationHandlerProvider(这个接口的默认实现 DefaultAuthorizationHandlerProvider,主要是用于收集 IAuthorizationHandler 并返回 IEnumerable<IAuthorizationHandler>)
2 实现说明IAuthorizationService 已默认实现,不需要我们做额外工作 。
IAuthorizationHandler 由 AuthorizationHandler<TRequirement> 实现 。
所以我们要做的,是:
第一步,准备 Requirement 实现 IAuthorizationRequirement
第二步,添加一个 Handler 程序继承 AuthorizationHandler<TRequirement> 并重写 HandleRequirementAsync 方法
关于具体实现,可以参考ASP.NET Core 认证与授权7:动态授权基于权限的授权部分,该文章思路已十分清晰,这里将其主要步骤列出来 。
3 定义权限项在实现 Requirement 之前,我们需要先定义一些权限项,主要用于后续作为 Policy 的名称,并传入 我们实现的 Requirement 之中 。
public static class UserPermission{public const string User = "User";public const string UserCreate = User + ".Create";public const string UserDelete = User + ".Delete";public const string UserUpdate = User + ".Update";}如上,定义了“增”、“删”、“改”等权限,其中 User 将拥有完整权限 。
4 实现 Requirementpublic class PermissionAuthorizationRequirement : IAuthorizationRequirement{public PermissionAuthorizationRequirement(string name){Name = name;}public string Name { get; set; }}使用 Name 属性表示权限的名称,与 UserPermission 中的常量对应 。
5 实现授权处理程序 Handler这里假定用户的 Claim 中 ClaimType 为 Permission 的项,如:
new Claim("Permission", UserPermission.UserCreate),new Claim("Permission", UserPermission.UserUpdate)如上,标识该用户用户 UserCreate 和 UserUpdate 的权限 。
注意:当然,实际程序我们肯定不是这样实现的,这里只是简易示例 。
接着,实现一个授权 Handler:
public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionAuthorizationRequirement>{protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement){var permissions = context.User.Claims.Where(_ => _.Type == "Permission").Select(_ => _.Value).ToList();if (permissions.Any(_ => _.StartsWith(requirement.Name))){context.Succeed(requirement);}return Task.CompletedTask;}}


推荐阅读