系统设计 / 访问控制 · 从 RBAC 查表到 policy 判定函数 / 为什么:在 User 和 Permission 之间插一层 Role 待审核 1 / 23
RBAC · why indirection

为什么:在 User 和 Permission 之间插一层 Role

最朴素的做法是 ACL(Access Control List):直接给每个用户挂一串权限。用户少时没问题,但用户和权限是一张全连接的网——M 个用户 × N 个权限根线。新人入职要逐条勾选;「所有编辑都加导出权限」这种策略变更,要逐个用户修改。RBAC 的核心改动只有一个:在中间插一层 Role,把 User→Permission 拆成 User→Role + Role→Permission,连线从 M×N 掉到 M+N。

1 · 两种模型的连线数

角色数 R 不进入乘积——它是「共享的策略包」,无论取何值,RBAC 的连线总数都是 M+N。

图 1-1 · 直接 ACL 与 RBAC 两种模型的连线数对照。可调用户数 M、权限数 N 与角色数 R,观察两侧连线总数的增长速度。

2 · 这层 indirection 的价值

  • 策略复用:「编辑能做的事」定义一次在 Editor 角色上,100 个编辑共享。改一处,全员生效。
  • 入职/转岗:给新人挂一个 Editor 角色即可,无需记住该勾哪 12 条权限。转岗 = 换角色。
  • 可审计:「谁能删订单」变成「哪些角色有 order:delete + 谁挂了这些角色」,两次关联即可查清。
  • 最小权限:角色让权限按职责打包,而不是为省事把所有人设成 admin。

注 · RBAC 有两条边:User → Role(谁是什么角色,见 最终生效集 的角色分配)和 Role → Permission(角色能做什么,见 Permission 的身份能力清单)。本系列就是沿这两条边展开的。

警示 · RBAC 不是银弹。它解决「能不能做」,但「对谁做」(只能改自己的 vs 所有人的)它管不了——那是 Scope / data-scope 的职责。混淆这两件事,会为了「只看自己的」之类的需求造出大量畸形角色。「能不能做」这一半由 Permission 的身份 展开。