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)。你可以把它理解成权限的"红绿灯"——不是所有角色都能随便分配。
常见的约束类型:
- 互斥角色:一个用户不能同时拥有两个互斥的角色。比如"出纳"和"会计"不能是同一个人。SDK里一般在角色分配时做校验。
- 基数约束:一个角色最多只能分配给N个用户。比如"系统管理员"最多3人,你不能把全公司1000人都塞进去。
- 先决条件角色:要获得角色A,必须先拥有角色B。比如必须先有"员工"角色,才能被分配"经理"角色。
- 会话约束:一个用户一次最多只能激活N个角色。这个在SDK里容易被忽略——用户登录后,你可能默认把他所有角色都激活了,实际上他只需要激活一个工作角色就够了。
我曾经在SDK里实现过"互斥角色"的实时校验。刚上线就出问题了:用户A本来有"管理员"和"普通用户"两个角色,我后端一查"管理员"和"普通用户"在配置表中被标记为互斥,直接报错不让登录。后来才知道,那个互斥配置是运维手滑写上去的数据库里其实不对。所以,约束一定要有「生效开关」和「校验级别」,生产环境可以设置为"警告但不阻断"。
约束在SDK中的设计原则:约束检查放在服务端,不能依赖客户端传参。但约束规则本身可以做成热配置,方便运维人员动态调整。
RBAC3:集大成者
RBAC3 = RBAC1 + RBAC2。它同时支持角色继承和约束。你可以想象一个层级严明的组织:角色可以继承,但继承路径上有互斥限制;角色基数也要控制。
说实话,RBAC3在实际项目中用得并不多。原因很简单:维护成本太高。我见过一个项目,角色树有7层,约束规则43条,结果权限管理员自己都搞不清某个用户到底能干什么。每次排查权限问题都要花半天时间画角色关系图。
我的建议:如果你的业务复杂度没到「银行权限审批」那种程度,优先用RBAC0+RABC2组合。继承关系会在约束校验时引入循环判断和权限计算膨胀,性能开销是指数级增长的。
四者的关系图谱
下面这张图可以让你一眼看清四个模型的关系。我习惯把它叫做"RBAC进化灯泡图"——从最基础的白炽灯到功能最全的智能灯。
表格对比:四者差异一览
光看图还不够,我一般习惯用表格把关键维度列出来,方便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到底需要哪种模型?别急着往上堆功能,先看看用户实际需要的权限管控粒度。有时候,少即是多。