Authorization 没有一个可以独立解释全部行为的 AuthorizationOptions 配置节。生产行为主要由服务装配、持久化 Provider、缓存基础设施、审计后端、种子和策略数据共同决定。本页按这些真实控制面组织参考信息。
1. Host 注册顺序
CoreRuntime 保证应用壳可解析:
- 注册 RBAC 与 AppScope;
- ABAC 与 ReBAC 使用始终 Neutral 的占位评估器;
- Feature Provider 使用固定 false 的
UnavailableFeatureDecisionProvider; - DataScope 使用无数据库依赖的简化 Resolver;
- 审计基础设施默认可以落到 Null Sink。
生产持久化分支先调用生成式 Adapter 注册,再调用 AddBitzOrcasAuthorizationPlatform(),加入真实策略评估器、完整 DataScope 和缓存 Adapter。
// ① 基础运行时提供可解析但受限的授权图,适合 Api Shell 与无数据库测试。services.AddBitzOrcasCoreRuntime(configuration);
// ② 公开扩展按配置选择 ORM,并完成审计、生成 Store 与授权基础设施装配。services.AddBitzOrcasPersistenceAdapters(configuration);
// PersistenceRegistration 内部按以下关键顺序执行:services.AddBitzOrcasAuditStore(configuration);services.AddBitzOrcasGeneratedPersistenceAdapters(persistenceProvider);services.AddBitzOrcasAuthorizationPlatform();最后三行表达内部顺序,业务 Host 应调用公开组合扩展,不要在外部重复注册同一组 Scoped Evaluator。
2. 服务清单与生命周期
| 服务 | CoreRuntime | 生产覆盖 / 追加 | 生命周期 |
|---|---|---|---|
IAuthorizationDecisionService | AuthorizationDecisionService | 同实现,依赖闭合 | Scoped |
| RBAC / AppScope Evaluator | 真实 | 保留 | Singleton |
| ABAC / ReBAC Evaluator | Null | 追加真实实现 | Scoped |
| Feature Provider | Unavailable=false | FeatureStore | 生成式 Adapter 生命周期 |
IDataScopeResolver | 简化构造 | 完整 DataScopeResolver | Scoped |
| Permission / ReBAC / DataScope / Feature Cache | 基础端口 | CacheStore*Cache | Singleton |
IAuthorizationAuditSink | Null | AuditLoggerDispatcher | Singleton |
DataScopeResolver 的组织成员查询由 Identity Infrastructure 的 OrganizationUnitMemberRepository 实现。这是窄端口协作,不是 Authorization 直接依赖 Identity Infrastructure 项目。
3. 持久化所有权
| 表 | 租户 | 软删除 | 关键唯一性 / 用途 |
|---|---|---|---|
SysRoleType | 全局 | 是 | RoleType 唯一 |
SysRole | 是 | 是 | TenantId + Name 唯一 |
SysUserRole | 是 | 是 | TenantId + UserId + RoleId 唯一 |
SysPermission | 全局 | 否 | Code 唯一的权限目录 |
SysRoleModulePermission | 是 | 是 | 角色或用户 + ModuleId + PermissionId 的过滤唯一索引 |
SysAbacRule | 是 | 是 | 按 TenantId + Module + ResourceType 查询 |
SysFeatureDefinition | 全局 | 是 | FeatureCode 唯一,保存 DefaultState |
SysFeatureOverride | 是 | 是 | TenantId + FeatureCode 唯一,只保存 OverrideState |
SysResourceRelation | 是 | 是 | TenantId + ResourceType + ResourceId + UserId 唯一 |
这些 *Record 是 owner-local 持久化模型,不是一对一复制业务聚合的旧式 Entity/Mapper 模式。它们通过编译期 Fluent Configuration Generator 消费 [BitzTable]、[BitzIndex] 与 [BitzColumn] 元数据。
3.1 稳定键规则
SysRole.Id是管理持久化 Id;Name是关系表使用的租户内稳定键;SysUserRole.UserId引用 Identity owner 的稳定业务键;SysPermission.Code是全局权限码,Mid归属 Menu 模块;SysResourceRelation只保存外部资源类型与 Id,不建立跨 bounded context 外键导航;- Feature 覆盖不存在时回退全局默认,删除覆盖不应复制或重写定义。
4. Store 分工
| 端口 | 写 / 读职责 | 不可用策略 |
|---|---|---|
IRoleStore | 角色、用户角色、角色权限的管理与查询 | [FailClosedPort] + BusinessClosedDefault |
IAbacRuleManagementStore | 管理 ABAC CRUD | Fail closed |
IAbacRuleStore | 决策引擎读取已启用规则 | 异常由 Evaluator 转 Deny |
IFeatureManagementStore | 定义管理与租户覆盖 Upsert | Fail closed |
IFeatureStore / IFeatureDecisionProvider | 读取租户合并状态 | 不存在或异常返回 disabled / empty |
IRelationStore | 查询实例关系与成员 | Result.Failure 由 ReBAC 转 Deny |
IAuthorizationAssignmentReader | 向主体投影提供角色和权限关系 | owner-local 只读端口 |
IAuthorizationSubjectReader | 由 Identity owner 确认目标用户 | 避免写入跨租户孤立 UserRole |
管理 Store 与运行时决策 Store 分离很重要:后台列表可以返回类型化 Result,安全评估则必须把不可用状态变成稳定 Deny。
5. 确定性种子
Authorization Infrastructure 提供以下 CSV 与 SeedStep:
| 顺序前缀 | 文件 | 内容 |
|---|---|---|
| 200 | 200-sys_role_type.csv | 全局角色类型 |
| 210 | 210-sys_role.csv | 初始租户角色 |
| 230 | 230-sys_permission.csv | 业务权限目录 |
| 240 | 240-sys_role_module_permission.csv | 初始角色—模块—权限关系 |
| 410 | 410-sys_feature_definition.csv | Feature 全局定义 |
| 520 | 520-sys_user_role.csv | 初始用户角色 |
权限还有 Governance Generator 从 [PermissionCatalog] / [PermissionDefinition] 收集的模块贡献。种子与生成目录必须做并集一致性检查,不能让代码有权限常量、数据库却没有对应目录行。
# 查看模块声明的权限事实;所有码应全局唯一并符合三段小写约定。rg -n "PermissionDefinition|public const string" \ src/Platform/Authorization/BitzOrcas.Platform.Authorization.Contracts -g '*.cs'
# 查看种子中的授权与 Feature 事实;新码必须同步迁移和幂等测试。rg -n "authorization\.|platform\." \ src/Platform/Authorization/BitzOrcas.Platform.Authorization.Infrastructure/Seeders/Assets -g '*.csv'6. 四类缓存不能混为一谈
| 缓存 | 默认策略 | 键的核心事实 | 失效维度 |
|---|---|---|---|
| Permission 决策 | Medium = 15 分钟 | 完整身份 + 资源 + 动作的 Hash | 用户、租户 |
| ReBAC 关系 | Short = 60 秒 | 租户 + 资源类型/Id + 用户 + 动作 | 资源 |
| DataScope | Medium = 15 分钟 | 租户 + 用户 + Office | 用户 |
| Feature | Medium = 15 分钟 | 租户 + FeatureCode | 租户 |
Permission 决策缓存的 Get/Set 是双层 best-effort:CacheStorePermissionCache 自己捕获,AuthorizationDecisionService 也捕获。各类 Adapter 的 Invalidate* 当前直接调用 RemoveByTag,失败会传播给管理 Handler。
await relations.UpsertAsync(relation, cancellationToken);
// ReBAC 正负结果都被缓存;新增、改角色或删除关系后必须按资源标签失效。await reBacCache.InvalidateByResourceAsync( relation.ResourceType, relation.ResourceId, cancellationToken);
// 如果关系同时改变主体装载或数据范围,还要失效对应的独立缓存。await dataScopeCache.InvalidateByUserAsync( relation.TenantId, relation.UserId, cancellationToken);这段代码描述写侧必须履行的协议。当前模块没有公开的 Relation 写 Store,因此资源 owner 需要提供受评审的实现,而不是直接写表后跳过失效。
7. Feature 全局更新的缓存范围
UpdateFeatureState 根据 IsTenantScoped 选择:
- 租户级:Upsert 当前租户覆盖,只失效该租户;
- 非租户级:修改全局 DefaultState,调用
InvalidateAllAsync失效全部 Feature 缓存。
全局更新与租户更新的范围现在一致。发布门禁仍要用两个租户和多个实例证明全局变更收敛,并验证租户覆盖不会误清其他租户的状态。
8. 集成事件
| 事件 | 触发场景 | 关键字段 |
|---|---|---|
RoleChangedIntegrationEvent | Created、Updated、Deleted | EventId、TenantId、RoleId、ChangeType、Actor、OccurredAt |
PermissionChangedIntegrationEvent | RoleAssigned、RoleRevoked、RolePermissionChanged | UserId、RoleId、PermissionId、ChangeType |
FeatureChangedIntegrationEvent | Feature 状态更新 | FeatureCode、IsEnabled、TenantId、Actor、OccurredAt |
这些事件当前没有 [IntegrationTopic],运行时主题使用事件类型全名。消费者不能自行猜短主题名;变更命名空间或类型名时要按版本化集成契约处理。
9. 双 ORM 契约与生产核验
生产同时支持 SqlSugar 与 EF Core 适配器时,至少验证:
- 所有 Tenant 表自动带可信租户过滤,Host 目录保持全局语义;
- 过滤唯一索引在两个 Provider 中表达等价;
- 软删除行不会参与角色、ABAC、Feature 和关系查询;
- 空结果与 Store 故障没有被同一种降级值混淆;
- 种子重复运行幂等,稳定键不漂移;
- 写入 + 集成事件的事务行为在两个 Provider 中一致。
10. 生产就绪检查
# 确认真实授权 Store 和 Evaluator 被注册,且 Host 进入持久化分支。rg -n "AddBitzOrcasGeneratedPersistenceAdapters|AddBitzOrcasAuthorizationPlatform" \ src/Hosts/BitzOrcas.Api/Composition -g '*.cs'
# 确认审计后端替换 Null Sink;至少应命中 SQL 或 Mongo 的 RemoveAll + AddSingleton。rg -n "RemoveAll<IAuthorizationAuditSink>|NullAuthorizationAuditSink" \ src/Framework -g '*.cs'
# 审查所有授权表的租户、软删除和唯一索引;预期每个关系表都有明确约束。rg -n "BitzTable|BitzIndex" \ src/Platform/Authorization/BitzOrcas.Platform.Authorization.Infrastructure/Persistence -g '*.cs'