功能模块

功能管理-FeatureManagement是在多租户应用程序中使用,检查定义的功能是否对当前租户有效,功能是否启用。Abp系统功能定义,类似于权限功能一种延伸。

  • FeatureDefinition : 功能定义

  • FeatureGroupDefinition : 功能组定义

  • FeatureValue : 功能值,记录功能是否可用

  • IFeatureValueProvider : 功能值提供器,负责检查功能是否可用。

一般会结合功能存储IFeatureStore使用

1
2
3
4
5
6
7
8
9
10
11
12
13
public abstract class FeatureValueProvider : IFeatureValueProvider, ITransientDependency
{
public abstract string Name { get; }

protected IFeatureStore FeatureStore { get; }

protected FeatureValueProvider(IFeatureStore featureStore)
{
FeatureStore = featureStore;
}

public abstract Task<string> GetOrNullAsync(FeatureDefinition feature);
}
  • IFeatureChecker : 功能检查,负责连接功能值提供器和功能定义提供器。
  • IFeatureDefinitionContext : 功能定义上下文,包含功能定义及操作功能定义

功能检查

1
2
3
4
5
6
public interface IFeatureChecker
{
Task<string> GetOrNullAsync([NotNull] string name);

Task<bool> IsEnabledAsync(string name);
}

功能定义提供器-FeatureDefinitionProvider

  • IFeatureDefinitionProvider : 功能定义提供器
  • IFeatureDefinitionManager : 功能管理器
1
2
3
4
5
6
7
8
9
10
11
public interface IFeatureDefinitionManager
{
[NotNull]
FeatureDefinition Get([NotNull] string name);

IReadOnlyList<FeatureDefinition> GetAll();

FeatureDefinition GetOrNull(string name);

IReadOnlyList<FeatureGroupDefinition> GetGroups();
}

继承FeatureDefinitionProvider,重写Define方法,调用IFeatureDefinitionContext内部方法AddGroup,添加功能组定义,FeatureGroupDefinitionAddFeature,可以增加子功能

功能使用

  • RequiresFeatureAttribute : 修饰于方法前,针对特定功能开放
  • DefaultValueFeatureValueProvider : 默认功能值提供器,直接返回功能定义,不作限制
  • TenantFeatureValueProvider : 租户功能值提供器,限制租户使用的功能
  • EditionFeatureValueProvider : 编辑功能值提供器,限制用户使用可编辑功能

功能存储

  • IFeatureStore : 从仓储中取功能值信息

权限模块

权限模块-PermissionManagement,是用于检查用户是否允许在应用程序中执行某些特定的操作。

Abp继承了ASP.NET Core Authorization,通过增加permissions作为自动策略使得允许授权系统在应用程序服务中可用

权限定义

  • PermissionDefinition : 单一权限,例如增删改
  • PermissionGroupDefinition : 权限组,例如对A的增删改,A就是分组

权限定义管理器

  • IPermissionDefinitionContext : 权限定义上下文,顾名思义,就是把权限和权限组定义存于这个类中
  • IPermissionDefinitionProvider : 权限定义提供者,负责在权限定义上下文绑定权限和权限组定义
  • IPermissionDefinitionManager : 权限定义管理,负责将上下文中的权限定义整合处理,对外提供调用

IPermissionDefinitionProvider接口定义

1
2
3
4
5
6
7
8
9
10
11
public interface IPermissionDefinitionProvider
{
// 定义权限之前
void PreDefine(IPermissionDefinitionContext context);

// 定义权限
void Define(IPermissionDefinitionContext context);

// 定义权限之后
void PostDefine(IPermissionDefinitionContext context);
}

开发者通过继承PermissionDefinitionProvider,在Define()方法内进行注册权限定义即可。
Abp框架会自动注入所有实现了IPermissionDefinitionProvider的类,在Abp.Authorization模块内部注册,在

自动注入方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static void AutoAddDefinitionProviders(IServiceCollection services)
{
var definitionProviders = new List<Type>();

services.OnRegistred(context =>
{
if (typeof(IPermissionDefinitionProvider).IsAssignableFrom(context.ImplementationType))
{
definitionProviders.Add(context.ImplementationType);
}
});

// 将获取到的 Provider 传递给 PermissionOptions 。
services.Configure<PermissionOptions>(options =>
{
options.DefinitionProviders.AddIfNotContains(definitionProviders);
});
}

IPermissionDefinitionManager接口定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface IPermissionDefinitionManager
{
// 根据权限定义的唯一标识获取权限,一旦不存在就会抛出 AbpException 异常。
[NotNull]
PermissionDefinition Get([NotNull] string name);

// 根据权限定义的唯一标识获取权限,如果权限不存在,则返回 null。
[CanBeNull]
PermissionDefinition GetOrNull([NotNull] string name);

// 获取所有的权限。
IReadOnlyList<PermissionDefinition> GetPermissions();

// 获取所有的权限组。
IReadOnlyList<PermissionGroupDefinition> GetGroups();
}

管理器会创建IPermissionDefinitionContext并传递给所有的PermissionDefinitionProvider,然后从上下文中取出权限保存管理器内部,绑定权限时再通过管理器获取到系统注册的所有权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
protected virtual Dictionary<string, PermissionGroupDefinition> CreatePermissionGroupDefinitions()
{
// 创建一个临时范围用于解析 Provider,Provider 解析完成之后即被释放。
using (var scope = _serviceProvider.CreateScope())
{
// 创建一个权限定义上下文。
var context = new PermissionDefinitionContext();

// 根据之前的类型,通过 IoC 进行解析出实例,指定各个 Provider 的 Define() 方法,会向权限上下文填充权限。
var providers = Options
.DefinitionProviders
.Select(p => scope.ServiceProvider.GetRequiredService(p) as IPermissionDefinitionProvider)
.ToList();

foreach (var provider in providers)
{
provider.PreDefine(context);
}

foreach (var provider in providers)
{
provider.Define(context);
}

foreach (var provider in providers)
{
provider.PostDefine(context);
}

// 返回权限组名称 - 权限组定义的字典。
return context.Groups;
}
}

创建一个继承自 PermissionDefinitionProvider 的类,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using Volo.Abp.Authorization.Permissions;

namespace Acme.BookStore.Permissions
{
public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var myGroup = context.AddGroup("BookStore");

myGroup.AddPermission("BookStore_Author_Create");
}
}
}

Abp会自动发现这个类,不需要进行配置

你需要在 Define 方法中添加权限组或者获取已存在的权限组,并向权限组中添加权限.

在定义权限后就可以在ASP.NET Core权限系统中当做策略名称使用.

权限值

  • IPermissionValueProvider
  • IPermissionValuesCheckContext : 负责承载权限值检查的上下文,含权限定义、用户声明

负责生成权限值提供者PermissionValueProvider,通过使用IPermissionStore取权限值检查IPermissionValuesCheckContext 上下文中ClaimsPrincipal是否获得权限许可。

Abp提供了三种权限值实现,分别是ClientRoleUser

  • ClientPermissionValueProvider : 从当前声明中拿到当前客户端并检查客户端是否具有指定的权限. 这在没有当前登录用户的客户端交互特别有用. 客户端声明由 AbpClaimTypes.ClientId 静态属性定义
  • RolePermissionValueProvider : 从当前的声明中拿到授予当前用户的角色集合并且判断角色是否具有指定的权限. 角色声明由 AbpClaimTypes.Role 静态属性定义
  • UserPermissionValueProvider : 从当前的声明中拿到当前用户ID并检查用户授权. 用户声明由 AbpClaimTypes.UserId 静态属性定义

开发者可以根据需求自己PermissionValueProvider拓展权限检查系统

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class SystemAdminPermissionValueProvider : PermissionValueProvider
{
public SystemAdminPermissionValueProvider(IPermissionStore permissionStore)
: base(permissionStore)
{
}

public override string Name => "SystemAdmin";

public async override Task<PermissionGrantResult>
CheckAsync(PermissionValueCheckContext context)
{
if (context.Principal?.FindFirst("User_Type")?.Value == "SystemAdmin")
{
return PermissionGrantResult.Granted;
}

return PermissionGrantResult.Undefined;
}
}

示例SystemAdminPermissionValueProvider允许声明User_Type值为SystemAdmin的用户授予所有权限. 通常在Provider中使用当前声明和 IPermissionStore.

PermissionValueProviderCheckAsync 应该返回下面三个值之一:

  • PermissionGrantResult.Granted 授予用户权限,如果没有其他的授权值提供程序返回 Prohibited, 那么最后会返回 Granted.
  • PermissionGrantResult.Prohibited 禁止授权用户,任何一个授权值提供程序返回了 Prohibited, 那么其他的提供程序返回的值都不再重要.
  • PermissionGrantResult.Undefined 代表当前无法确定是否授予或禁止权限, 返回UnDefined由其他权限值提供程序检查权限.

定义Provider后将其添加到 AbpPermissionOptions,如下所示:

1
2
3
4
Configure<AbpPermissionOptions>(options =>
{
options.ValueProviders.Add<SystemAdminPermissionValueProvider>();
});

权限检查管理器

  • IPermissionValueProviderManager : 负责提供权限设定值,可以从存储中获取,也可以从配置里获取

负责管理应用程序中或者权限存储中的权限值,统一访问管理器

IPermissionValueProviderManager接口定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public interface IPermissionValueProviderManager
{
IReadOnlyList<IPermissionValueProvider> ValueProviders { get; }
}

public class PermissionValueProviderManager : IPermissionValueProviderManager, ISingletonDependency
{
public IReadOnlyList<IPermissionValueProvider> ValueProviders => _lazyProviders.Value;
private readonly Lazy<List<IPermissionValueProvider>> _lazyProviders;

protected AbpPermissionOptions Options { get; }

public PermissionValueProviderManager(
IServiceProvider serviceProvider,
IOptions<AbpPermissionOptions> options)
{
Options = options.Value;

_lazyProviders = new Lazy<List<IPermissionValueProvider>>(
() => Options
.ValueProviders
.Select(c => serviceProvider.GetRequiredService(c) as IPermissionValueProvider)
.ToList(),
true
);
}
}

权限管理

Abp连接权限定义和权限值

  • IPermissionChecker : 权限检查

权限检查类

1
2
3
4
5
6
7
8
9
10
public interface IPermissionChecker
{
Task<bool> IsGrantedAsync([NotNull]string name);

Task<bool> IsGrantedAsync([CanBeNull] ClaimsPrincipal claimsPrincipal, [NotNull]string name);

Task<MultiplePermissionGrantResult> IsGrantedAsync([NotNull]string[] names);

Task<MultiplePermissionGrantResult> IsGrantedAsync([CanBeNull] ClaimsPrincipal claimsPrincipal, [NotNull]string[] names);
}

结合微软权限策略

  • PermissionRequirement : 实现微软官方IAuthorizationRequirement,Abp自定义权限拓展
  • PermissionRequirementHandler : 实现微软官方AuthorizationHandler<PermissionRequirement>,对权限值、权限定义、用户声明进行鉴权

最终PermissionRequirementHandler会使用IPermissionChecker权限检查,Abp默认实现了PermissionCheckerPermissionChecker用到了上述IPermissionDefinitionManagerIPermissionValueProviderManagerICurrentPrincipalAccessorICurrentTenant

微软提供的鉴权规范
  • AuthorizationPolicy : 微软提供集认证方案和若干IAuthorizationRequirement于一身
  • DefaultAuthorizationPolicyProvider : 微软默认实现策略提供器
  • IAuthorizationRequirement : 权限拓展
  • AuthorizationHandler : 权限处理

IAbpAuthorizationPolicyProvider 继承了IAuthorizationPolicyProvider

参阅 基于策略的授权 文档了解如何自定义策略.

1
2
3
4
public interface IAbpAuthorizationPolicyProvider : IAuthorizationPolicyProvider
{
Task<List<string>> GetPoliciesNamesAsync();
}

AbpAuthorizationPolicyProvider继承AspNetCore提供的DefaultAuthorizationPolicyProvider

该提供器负责从PermissionDefinitionManager获取权限定义生成AuthorizationPolicy

权限存储

  • IPermissionStore : 存储权限值

负责实现权限存储,从各自领域的仓储中取出权限值,Abp的Permission模块已经实现这块功能。