[Abp vNext 源码分析] - 7. 权限与验证 (5)

继续回到权限管理器,权限管理器的接口定义是 IPermissionDefinitionManager ,从接口的方法定义来看,都是获取权限的方法,说明权限管理器主要提供给其他组件进行权限校验操作。

public interface IPermissionDefinitionManager { // 根据权限定义的唯一标识获取权限,一旦不存在就会抛出 AbpException 异常。 [NotNull] PermissionDefinition Get([NotNull] string name); // 根据权限定义的唯一标识获取权限,如果权限不存在,则返回 null。 [CanBeNull] PermissionDefinition GetOrNull([NotNull] string name); // 获取所有的权限。 IReadOnlyList<PermissionDefinition> GetPermissions(); // 获取所有的权限组。 IReadOnlyList<PermissionGroupDefinition> GetGroups(); }

接着我们来回答 2.2.1 末尾提出的问题,权限组是根据 Provider 自动创建了,那么权限呢?其实我们在权限管理器里面拿到了权限组,权限定义就很好构建了,直接遍历所有权限组拿它们的 Permissions 属性构建即可。

protected virtual Dictionary<string, PermissionDefinition> CreatePermissionDefinitions() { var permissions = new Dictionary<string, PermissionDefinition>(); // 遍历权限定义组,这个东西在之前就已经构建好了。 foreach (var groupDefinition in PermissionGroupDefinitions.Values) { // 递归子级权限。 foreach (var permission in groupDefinition.Permissions) { AddPermissionToDictionaryRecursively(permissions, permission); } } // 返回权限唯一标识 - 权限定义 的字典。 return permissions; } protected virtual void AddPermissionToDictionaryRecursively( Dictionary<string, PermissionDefinition> permissions, PermissionDefinition permission) { if (permissions.ContainsKey(permission.Name)) { throw new AbpException("Duplicate permission name: " + permission.Name); } permissions[permission.Name] = permission; foreach (var child in permission.Children) { AddPermissionToDictionaryRecursively(permissions, child); } } 2.2.4 授权策略提供者的实现

我们发现 ABP vNext 自己实现了 IAbpAuthorizationPolicyProvider 接口,实现的类型就是 AbpAuthorizationPolicyProvider 。

这个类型它是继承的 DefaultAuthorizationPolicyProvider ,重写了 GetPolicyAsync() 方法,目的就是将 PermissionDefinition 转换为 AuthorizationPolicy 。

如果去看了 雨夜朦胧 大神的博客,就知道我们一个授权策略可以由多个条件构成。也就是说某一个 AuthorizationPolicy 可以拥有多个限定条件,当所有限定条件被满足之后,才能算是通过权限验证,例如以下代码。

public void ConfigureService(IServiceCollection services) { services.AddAuthorization(options => { options.AddPolicy("User", policy => policy .RequireAssertion(context => context.User.HasClaim(c => (c.Type == "EmployeeNumber" || c.Type == "Role"))) ); // 这里的意思是,用户角色必须是 Admin,并且他的用户名是 Alice,并且必须要有类型为 EmployeeNumber 的 Claim。 options.AddPolicy("Employee", policy => policy .RequireRole("Admin") .RequireUserName("Alice") .RequireClaim("EmployeeNumber") .Combine(commonPolicy)); }); }

这里的 RequireRole() 、RequireUserName()、RequireClaim() 都会生成一个 IAuthorizationRequirement 对象,它们在内部有不同的实现规则。

public AuthorizationPolicyBuilder RequireClaim(string claimType) { if (claimType == null) { throw new ArgumentNullException(nameof(claimType)); } // 构建了一个 ClaimsAuthorizationRequirement 对象,并添加到策略的 Requirements 组。 Requirements.Add(new ClaimsAuthorizationRequirement(claimType, allowedValues: null)); return this; }

这里我们 ABP vNext 则是使用的 PermissionRequirement 作为一个限定条件。

public override async Task<AuthorizationPolicy> GetPolicyAsync(string policyName) { var policy = await base.GetPolicyAsync(policyName); if (policy != null) { return policy; } var permission = _permissionDefinitionManager.GetOrNull(policyName); if (permission != null) { // TODO: 可以使用缓存进行优化。 // 通过 Builder 构建一个策略。 var policyBuilder = new AuthorizationPolicyBuilder(Array.Empty<string>()); // 创建一个 PermissionRequirement 对象添加到限定条件组中。 policyBuilder.Requirements.Add(new PermissionRequirement(policyName)); return policyBuilder.Build(); } return null; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzzps.html