第三章 RBAC扩展模型:会话角色、动态职责分离、约束规则
3.1 边界:从静态分配到动态管控
核心RBAC(RBAC0)只解决了“用户→角色→权限”的静态分配链路,但在以下场景中暴露边界缺陷:
- 临时提权:运维工程师需要临时切换到高权限角色,完成后自动恢复。
- 职责分离冲突:同一个人同时被赋予“采购员”和“审批员”角色,但在一次业务流中不能同时使用两个角色。
- 角色数量失控:一个角色允许分配的最大用户数未加限制,导致权限被滥用。
RBAC扩展模型(RBAC1/2/3)在核心RBAC基础上引入会话角色(Session Roles)、动态职责分离(Dynamic Separation of Duty,DSoD)以及约束规则(基数、前提、互斥),将权限控制的边界从“定义时”延伸到“运行时”。
3.2 分层:扩展模型的三层结构
扩展模型在标准NIST RBAC参考模型(INCITS 359-2012)中分层如下:
| 层次 | 核心组件 | 新增能力 |
|---|---|---|
| RBAC0 — 核心层 | User、Role、Permission、User-Role Assignment (UA)、Role-Permission Assignment (PA) | 静态授权基础 |
| RBAC1 — 角色继承层 | Role Hierarchy(角色层级) | 上级角色自动继承下级权限,简化PA管理 |
| RBAC2 — 约束层 | 约束规则引擎(基数、前提、互斥) | 控制UA/PA的合法条件,防止冲突 |
| RBAC3 — 会话层(综合层) | Session、激活角色集、DSoD | 运行时激活/禁用角色,动态检查冲突 |
本章聚焦RBAC2 + RBAC3中的三个关键扩展。
3.3 组件职责
- 会话 (Session):代表用户的一次登录生命周期,每个会话持有一个
激活角色集 (activated_roles)。用户可同时激活多个角色,但受约束限制。 - 角色基数约束 (Cardinality):限制一个角色最多可被分配的用户数(直接约束),或一个用户最多可拥有的角色数(垂直约束)。
- 前提约束 (Prerequisite):用户必须已经拥有角色A,才能被分配角色B(例如:只有“项目成员”才能被授予“项目经理”)。
- 互斥约束 (Mutually Exclusive):两个角色不能被同时分配给同一个用户,或在同一个会话中同时激活。又分为静态互斥(SSD)和动态互斥(DSD)。
- 动态职责分离 (DSoD):在会话激活阶段检查。例如“同一用户不能同时激活‘提交订单’和‘审核订单’角色”,允许分配两者,但运行时二选一。
3.4 数据流与控制流:运行时约束检查路径
以下流程图描述了一个用户创建会话并尝试激活角色时的完整控制流:
1. 用户登录 → 系统创建Session,初始激活角色集为空
2. 用户请求激活角色R
3. 系统检查激活角色集是否已达会话角色基数上限?
→ 若超限,拒绝并返回“会话角色数超限”
4. 系统检查R是否与当前已激活角色存在DSoD冲突?
→ 遍历所有活跃角色的互斥列表,若发现冲突,拒绝
5. 系统检查R是否满足前提约束?
→ 若R有前置角色P要求,检查P是否在用户已分配角色集中(不一定已激活),否则拒绝
6. 若所有检查通过 → 将R加入激活角色集,返回成功
7. 用户请求执行权限操作 → 权限引擎根据激活角色集中的所有角色计算并集授权
关键点:基数约束通常在UA(用户-角色分配)时检查,而互斥约束可在UA时(SSD)或会话激活时(DSD)检查。动态互斥只在会话层生效,不阻止用户同时拥有两个角色。
3.5 内联SVG:RBAC扩展模型核心架构与约束检查流
3.6 选型权衡
| 维度 | 核心RBAC(RBAC0) | 扩展RBAC(RBAC2+3) |
|---|---|---|
| 职责分离粒度 | 仅靠静态UA分配避免冲突(需人工审核) | SSD+DSD双重保障,运行时自动阻断 |
| 灵活性 | 低:用户一旦分配角色,立即拥有所有权限 | 中:通过会话激活控制,支持临时提权与降权 |
| 实现复杂度 | 简单 | 中等:需要约束引擎、会话管理、激活检查 |
| 性能影响 | 授权时无运行时开销 | 每次激活/权限操作需额外约束检查 |
| 典型场景 | 小型系统、静态角色定义明确的组织 | 金融系统、多级审批、需要细粒度的实时控制 |
选择建议:若业务要求“一人可拥有多角色但不可同时使用”,或“角色数量需动态限制”,则必须引入扩展RBAC。否则纯RBAC0即可满足。
3.7 风险点
- 约束逻辑冲突:基数、前提、互斥条件可能产生循环依赖(如角色A要求先有角色B,而角色B又要求先有角色A),需在UA时进行有向图环检测。
- 会话膨胀:如果用户频繁切换激活角色集,可能产生大量冗余会话,需设置会话超时与最大活跃数。
- DSD误判:动态互斥的检查时机(每次激活 vs. 每次权限操作前)不同,如果仅检查激活时机,可能出现“激活后权限变更”导致的漏洞。
- 性能热点:在高并发场景下,每次权限决策都需要查询约束规则表,应引入缓存与规则编译。
3.8 落地步骤
- 审计现有角色分配:梳理所有用户-角色分配,标记已存在的冲突(如一人同时拥有互斥角色)。
- 定义约束规则元数据:建立
cardinality_rule、prerequisite_rule、mutual_exclusion_rule三张配置表。 - 扩展核心RBAC数据模型:添加
session表、session_roles关联表、dynamic_exclusion表(用于记录DSD对) - 实现约束检查器:抽象成独立模块,提供
check_activation(user_id, role_id, session_id)接口,返回拒绝或通过。 - 兼容旧分配:对已有UA运行全量约束检查,标记违规记录并通知管理员手动修正。
- 灰度切换:先对非核心业务启用DSD,确认无副作用后全量上线。
- 监控与报警:记录所有约束拒绝事件,用于后续分析角色设计合理性。
3.9 验收标准
| 验收点 | 验证方法 | 预期结果 |
|---|---|---|
| 基数约束 | 尝试为某个已满角色添加第N+1个用户 | UA操作被拒绝,返回具体错误信息 |
| 前提约束 | 直接为用户分配一个需要前置角色的角色(用户未拥有前置角色) | UA操作被拒绝,提示缺少前置角色 |
| 静态互斥(SSD) | 为用户分配一对互斥角色中的第二个 | UA操作被拒绝 |
| 动态互斥(DSD) | 用户已激活角色A,在同一个会话中尝试激活互斥角色B | 激活请求被拒绝,已激活角色A保持不变 |
| 会话切换 | 用户停用角色A后再激活角色B,再激活角色A | 均允许,无冲突(若DSD仅在激活时检查对集) |
| 性能 | 高并发下持续激活/权限操作 | P99延迟不超过基线(纯RBAC)的30% |
注意:验收时务必覆盖边界条件,例如“同一角色多次激活”、“用户注销后会话残留”等。建议使用自动化测试用例持续集成。