RBAC核心模型:从0到3的进化之路

要说清楚RBAC在SDK里怎么落地,得先搞懂它的四个核心模型。很多人一上来就谈RBAC3,结果连RBAC0都没吃透。我见过不少团队,把角色继承和约束混在一起,最后权限炸锅。

今天咱们就把这四个模型拆开看。从最简单的RBAC0,到最完整的RBAC3。每个模型解决什么问题、适合什么场景、SDK适配时要注意什么,我都会结合自己的踩坑经历讲明白。

RBAC0:一切的基础

RBAC0是权限控制的最小单元。说白了就是三张表:用户、角色、权限。用户和角色是多对多,角色和权限也是多对多。SDK里最常用这层模型,比如给用户分配一个“管理员”角色,这个角色拥有“创建订单”和“删除订单”的权限。

有一点要记住:RBAC0本身没有角色继承,也没有任何约束。你可以让一个用户直接拥有多个角色,但角色之间是平级的。我在第一个项目里就犯过这个错——把"超级管理员"和"普通管理员"放到同一个层面,后来发现权限重叠得厉害。

核心公式:用户 ↔ 角色 ↔ 权限(双向多对多)

SDK中至少需要实现三张表:sys_user_role、sys_role_permission,再加一张sys_permission。

你的SDK如果只做轻量级权限控制,比如一个内部工具包,RBAC0就够用了。为什么呢?因为它的查询路径最短:用户→角色→权限,一次连表查询就能出结果。

个人建议:除非你明确需要角色等级或约束规则,否则永远从RBAC0起步。过度设计是权限SDK最大的坑。

RBAC1:角色也能"继承"

现实世界里角色是有层级的。部门经理能做的事,普通员工基本也能做,但反过来不行。RBAC1就是为了解决这个痛点——它引入了角色继承(Role Hierarchy)。

继承分两种:

  • 通用继承:子角色自动拥有父角色的所有权限。比如"管理员"继承"普通用户"。
  • 受限继承:允许部分继承,可以指定某些权限不被子角色继承。这种方式我在一个金融SDK里用过——"风控主管"继承"审核员"的大部分权限,但"注销账户"这种高危操作不继承。

嗯,这里要注意:继承关系不能形成循环。A继承B、B继承C、C再继承A?不行。我在审查代码时发现过这种死循环,原因是数据库里不小心插了一条自己指向自己的记录。

避坑指南:实现角色继承时,一定要做DAG(有向无环图)检测。我曾经依赖程序逻辑去判断,后来数据量大了,递归查询直接撑爆连接池。改用预计算「祖先路径」字段,性能才稳住。

RBAC2:给权限上"锁"

RBAC2在RBAC0的基础上加了约束(Constraints)。你可以把它理解成权限的"红绿灯"——不是所有角色都能随便分配。

常见的约束类型:

  1. 互斥角色:一个用户不能同时拥有两个互斥的角色。比如"出纳"和"会计"不能是同一个人。SDK里一般在角色分配时做校验。
  2. 基数约束:一个角色最多只能分配给N个用户。比如"系统管理员"最多3人,你不能把全公司1000人都塞进去。
  3. 先决条件角色:要获得角色A,必须先拥有角色B。比如必须先有"员工"角色,才能被分配"经理"角色。
  4. 会话约束:一个用户一次最多只能激活N个角色。这个在SDK里容易被忽略——用户登录后,你可能默认把他所有角色都激活了,实际上他只需要激活一个工作角色就够了。

我曾经在SDK里实现过"互斥角色"的实时校验。刚上线就出问题了:用户A本来有"管理员"和"普通用户"两个角色,我后端一查"管理员"和"普通用户"在配置表中被标记为互斥,直接报错不让登录。后来才知道,那个互斥配置是运维手滑写上去的数据库里其实不对。所以,约束一定要有「生效开关」和「校验级别」,生产环境可以设置为"警告但不阻断"。

约束在SDK中的设计原则:约束检查放在服务端,不能依赖客户端传参。但约束规则本身可以做成热配置,方便运维人员动态调整。

RBAC3:集大成者

RBAC3 = RBAC1 + RBAC2。它同时支持角色继承和约束。你可以想象一个层级严明的组织:角色可以继承,但继承路径上有互斥限制;角色基数也要控制。

说实话,RBAC3在实际项目中用得并不多。原因很简单:维护成本太高。我见过一个项目,角色树有7层,约束规则43条,结果权限管理员自己都搞不清某个用户到底能干什么。每次排查权限问题都要花半天时间画角色关系图。

我的建议:如果你的业务复杂度没到「银行权限审批」那种程度,优先用RBAC0+RABC2组合。继承关系会在约束校验时引入循环判断和权限计算膨胀,性能开销是指数级增长的。

四者的关系图谱

下面这张图可以让你一眼看清四个模型的关系。我习惯把它叫做"RBAC进化灯泡图"——从最基础的白炽灯到功能最全的智能灯。

RBAC核心模型进化关系 RBAC0 基础角色-权限映射 RBAC1 角色继承(层级) RBAC2 约束限制 + + 继承 约束 RBAC3 继承+约束全功能 虚线:可选组合 实线:标准演化链路 注:RBAC3需要同时 处理继承和约束兼容

表格对比:四者差异一览

光看图还不够,我一般习惯用表格把关键维度列出来,方便SDK选型时对着看。

特性 RBAC0 RBAC1 RBAC2 RBAC3
角色继承 ❌ 无 ✅ 有 ❌ 无 ✅ 有
约束限制 ❌ 无 ❌ 无 ✅ 有 ✅ 有
实现复杂度 低 中 中 高
查询性能 最快 较快(需递归) 中等(加约束校验) 最慢(递归+校验)
典型适用场景 小型CMS、管理 企业组织结构 金融、合规系统 大型企业ERP
SDK推荐度 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐

SDK适配时该怎么选?

这个选择题其实不难。我给一个简单粗暴的经验法则:

  • 你的SDK只做工具类库,内部使用 → RBAC0,别想太多。
  • 用户组织有明确层级,比如部门经理、总监 → 加RBAC1,但继承层数控制在3层以内。
  • 需要防止权限滥用,比如互斥账户 → 加RBAC2,但约束规则总数最好不超过20条。
  • 全都要? → RBAC3,但你要准备好缓存和异步权限变更通知,否则每次用户请求都得重新算一遍权限。

个人实践:我参与过一个开源SDK,早期版本用的RBAC3,后来发现大部分场景根本用不到继承。我们果断降级为RBAC0+RBAC2,把继承逻辑做成插件化——用户需要继承可以自己装插件包,核心SDK保持轻量。上线后SDK体积缩小了60%,接口响应时间降低了40%。

嗯,说到这,你可以回想一下:你手上的SDK到底需要哪种模型?别急着往上堆功能,先看看用户实际需要的权限管控粒度。有时候,少即是多。