系统设计 / 访问控制 · 从 RBAC 查表到 policy 判定函数 / 最终生效集:User Override 怎么盖过 Role 待审核 5 / 23
resolve · union − deny + allow

最终生效集:User Override 怎么盖过 Role

一个用户可以同时挂多个角色(User → Role → Permission 的关系见 为什么 RBAC),权限先求并集。但角色是「粗粒度的包」,总有个例:「这个编辑特别信任,额外给他导出权限」「那个管理员最近要冻结他的删除权」。于是在角色之上再加一层用户级 Override

1 · 生效集的公式

effective = union(RolePermission) − UserDeny + UserAllow

顺序是关键:先减 Deny,再加 Allow——所以 Allow 后置、能盖过 Deny(显式放行优先)。

图 1-1 · 角色并集经用户级 Deny 与 Allow 修正后的最终生效集。勾 editor 角色后在 Deny 里点 article:update 可见它从并集消失,再在 Allow 里点同一条则重新出现。

2 · 四个盒子的读法

  • union(Roles):所勾角色授予的权限并集(去重)。被 Deny 命中的会画上删除线。
  • − Deny:命中并集的才真正被移除;Deny 一条角色本就没授予的权限,不产生任何效果。
  • + Allow:并集里没有的才是「新增」(绿色);若 Allow 的恰好刚被 Deny 掉,它会把那条补回来。
  • = Effective:最终 can(key) 返回 true 的集合。

警示 · Deny 优先还是 Allow 优先,是一个设计选择,必须写进文档。本系列按公式 − deny + allow 让 Allow 生效(后置)。不少企业系统采用相反策略:Deny 永远优先(更保守,黑名单一律否决)。无论哪种,关键是团队统一、可解释——排查问题时能直接说清「这条权限为什么有/没有」。