RBAC vs ABAC vs ReBAC:三种权限模型怎么选
一个新来的后端工程师接到第一张权限工单:给「订单中心」加一个「导出报表」的按钮,只让运营和财务用。
他做完之后问了自己一个问题:运营小满点下这个按钮,她能看到哪些订单?
团队里三个人给了三个答案:
- 「她是运营组的,运营组有这个权限」——按岗位算;
- 「工作日 9 点到 18 点、公司内网、且订单状态是已完结,才放行」——按条件算;
- 「她只能看自己跟进的店铺的订单」——按关系算。
三个答案都没错,但它们说的是三件不同的事。这就是权限系统里最容易踩的第一个坑:把三个问题当成了一个。
「他能不能看」,只有三种问法
任何一句「他能不能看」,拆开都落在三种问法里:
| 问法 | 凭据 | 对应的模型 |
|---|---|---|
| 他是哪类人? | 他戴哪张工牌(岗位、角色) | RBAC |
| 他符不符合条件? | 他身上的一堆属性,当场比对 | ABAC |
| 他和这条数据有没有关系? | 他和数据之间连着的线 | ReBAC |
- RBAC(Role-Based Access Control,基于角色的访问控制):把权限打包成「角色」,人挂角色。改一次角色,挂它的人一起变。
- ABAC(Attribute-Based Access Control,基于属性的访问控制):不预先打包,拿主体、对象、操作、环境四类属性当场算——「是不是财务」「是不是工作日」都只是属性之一。
- ReBAC(Relationship-Based Access Control,基于关系的访问控制):看用户和对象之间的关系图——「小满和张老板是不是同一个团队的」「这份文档是不是小满建的」。
三套办法答的是三个不同的问题:按岗位答「他这类人能不能」;按条件答「他这条件能不能」;按关系答「他和这东西能不能」。 选型的第一步,不是背名词,是想清楚你到底在问哪一句。
时间线:这套东西不是拍脑袋发明的
权限模型的每一步进化,都对应一次被现实打脸。
| 时间 | 事件 | 解决的问题 |
|---|---|---|
| 早期 | ACL / DAC:「一人一张清单,谁拥有谁决定」 | 有清单可查,但人一多就管不动 |
| 早期 | MAC:军事多级安全标签 | 强制按密级管控,但刚性 |
| 1992-10-13 | Ferraiolo 与 Kuhn(NIST)提出 RBAC:权限绑角色、不绑个人 | 人员流动频繁时不必逐人改清单 |
| 1996 | Sandhu 等人发表《Role-Based Access Control Models》(IEEE Computer 29(2)) | 给出 RBAC0–RBAC3 的分档框架 |
| 2000 | NIST 统一为 NIST RBAC 模型 | 行业有了一致的参照 |
| 2004-02-11 | 通过为美国国家标准 ANSI/INCITS 359-2004(2012-05-29 修订为 INCITS 359-2012) | RBAC 成为正式标准 |
| 2014-01 | NIST 发布 SP 800-162《Guide to ABAC》(2019-02 勘误更新) | ABAC 有了定义与考量清单 |
| 2019 | Google 发表 Zanzibar 论文(USENIX ATC 2019) | 关系法被证明可以做到全球规模 |
一句话概括这条线:从「给个人发钥匙」到「给岗位发钥匙」,再到「按条件发钥匙」,最后到「按关系发钥匙」——每换一种问法,就换一种钥匙。
RBAC:按岗位,最主流的那套
RBAC 的核心操作只有三步:权限打包成角色 → 人挂角色 → 判定时查角色。
它成为企业与多租户系统的主流默认,不是没有原因的:改一次角色,挂这个角色的人一起变;要审计「谁有导出权限」,查角色名单即可;判定行为稳定、可预期。
但「RBAC」这四个字母下面,其实还分四档(Sandhu 1996 的 RBAC0–RBAC3):
| 档 | 多了什么 | 补了哪个洞 | 代价 |
|---|---|---|---|
| RBAC0 打底 | 权限打包成「套餐」挂人 | 一人一张清单管不动 | 套餐一多就乱 |
| RBAC1 能套 | 大套餐自动带上小套餐的每一项(角色继承) | 改一样要动一片 | 套过头会多出看不见的「能做的事」 |
| RBAC2 相冲 | 两份相冲的套餐不许落在同一人(职责分离) | 一个人从头做到尾,出事查不清 | 只拦得住你列出来的冲突对 |
| RBAC3 | 继承 + 相冲都要 | 人多岗细,单靠一样不够 | 齐全,但也要花心思打理 |
NIST 的统一模型把同样的事情叫作四个组件:Core(平铺的用户-角色-权限)、Hierarchical(层级继承)、Static SoD 与 Dynamic SoD(静态/动态职责分离)。
RBAC 的硬边界:遇到「哪一条数据」这个问题,它答不了。运营有「查看订单」权限——但她能看的是全平台的订单,还是自己店铺的订单?这要靠数据范围来收窄,我们会在另一篇里展开。
角色爆炸:RBAC 最真实的代价
RBAC 用久了,最容易长出来的是「角色爆炸」。Kuhn、Coyne 与 Weil 在 2010 年《Adding Attributes to Role-Based Access Control》(IEEE Computer 43(6))里指出:大型组织的 RBAC 部署可能需要成百上千个角色。
原因很朴素:业务只差「一点点」条件——「华东区财务」「华东区财务但只在月末」「华东区财务但只在月末且只能看已完结订单」——每一种都新建一个角色,角色表就变成了业务条件表的穷举。
这也是 ABAC 登场的直接动机:与其把条件的每一种组合都预煮成角色,不如把条件本身交给判定引擎当场算。
ABAC:按条件,灵活但难伺候
ABAC 的官方定义来自 NIST SP 800-162(2014-01,2019-02 勘误更新):判定基于主体、对象、操作、环境四类属性。
举一个典型的 ABAC 规则(XACML 风格):
<Rule Effect="Permit">
<Target>
<AnyOf><Match MatchId="string-equal">
<AttributeValue>export</AttributeValue>
<AttributeDesignator Category="action" AttributeId="action-id"/>
</Match></AnyOf>
</Target>
<Condition>
<Apply FunctionId="and">
<Apply FunctionId="string-equal">
<AttributeValue>finance</AttributeValue>
<AttributeDesignator Category="subject" AttributeId="department"/>
</Apply>
<Apply FunctionId="time-in-range">
<AttributeValue>09:00:00/18:00:00</AttributeValue>
<EnvironmentAttributeDesignator AttributeId="current-time"/>
</Apply>
</Apply>
</Condition>
</Rule>
好处一眼可见:条件变了,改规则;不需要新建角色。代价同样明显:
- 规则容易绕——多条规则叠加,最终谁能干什么,很难一眼看懂;
- 算得慢——每次判定要实时取属性(部门、时间、位置……),比查一张角色表重;
- 难审计——「他为什么有权限」的答案是一条条规则求值出来的,不是一张名单。
ABAC 不是「更高级的 RBAC」。它把复杂度从「角色表」搬到了「规则库」——复杂度没有消失,只是换了地方。
ReBAC:按关系,答「这条数据归谁」
ReBAC 的思路来自社交网络时代:数据天生带关系——文档属于文件夹、文件夹属于团队、团队里有成员。与其给「团队」发一个角色,不如在用户和对象之间存一根「线」,判定时问:从这个人出发,能不能走到这个对象?
Google 的 Zanzibar(2019)是这个思路的工业级证明。论文给出的数字:
- 系统承载两万亿条以上的访问控制关系(trillions of ACLs);
- 每秒处理数百万次授权请求(millions of authorization requests per second);
- 三年间可用性 99.999%,95 分位延迟低于 10 毫秒。
代价是:关系能层层传递,牵一发动全身;元组量巨大,存与查都重。它适合「对象级共享与归属」——云盘、协作文档、社交关系;不适合拿来当所有权限的底座。
三种模型对比
| 维度 | RBAC(按岗位) | ABAC(按条件) | ReBAC(按关系) |
|---|---|---|---|
| 凭啥判 | 你戴哪张工牌 | 你身上的一堆条件,当场比对 | 你和这条数据有没有连线 |
| 答的问题 | 他这类人能不能 | 他这条件能不能 | 他和这东西能不能 |
| 粒度 | 粗(资源:动作) | 细(任意条件组合) | 细(对象级、可传递) |
| 好处 | 简单、好查、稳定 | 灵活、动态、随条件变 | 天然表达层级/共享/归属 |
| 代价 | 角色爆炸、静态、不吃上下文 | 规则易绕、难一眼看懂、算得慢 | 牵一发动全身、元组量大、存查重 |
| 标准 | INCITS 359 / NIST RBAC | NIST SP 800-162 / OASIS XACML | Zanzibar(2019)/ NGAC |
| 一句话 | 按岗位发权限 | 按条件判权限 | 按关系判权限 |
怎么选:先问你问的是哪种问题
| 你要管的 | 用哪套 | 为什么 |
|---|---|---|
| 一类人(同一岗位常做的事) | 按岗位 | 省事、好查 |
| 时间、部门、设备这类条件 | 按条件 | 灵活,不用穷举角色 |
| 「这条数据到底归谁」 | 按关系 | 贴切,可传递 |
| 现实(几样都要) | 混着用 | 多数系统不是三选一,而是打底 + 收窄 + 顶细节 |
flowchart TD
Q{"你管的是什么?"} -->|"一类人"| R["RBAC · 按岗位<br/>省事、好查"]
Q -->|"一堆条件"| A["ABAC · 按条件<br/>灵活、动态"]
Q -->|"这条数据归谁"| B["ReBAC · 按关系<br/>贴切、可传递"]
R --> M["多数系统不是三选一<br/>而是打底 + 收窄 + 顶细节"]
A --> M
B --> M
图 1:选型决策流——先问「你管的是什么」,模型跟着问题走;现实系统多半三层叠着用。
两条常被忽略的选型纪律:
- 更细的办法,不等于更安全。 规则配不好,再细也照样漏;ReBAC 的线画歪了,照样把不该看的数据连过去。
- 三套都不能替代「最小权限」这条纪律。 这条纪律比选型更早:Saltzer 与 Schroeder 在 1975 年就写下了「只给刚好够用的权限」。一个著名的反面教材是 Capital One(2019):一个权限过宽的云角色被利用,约 1.06 亿用户与申请人的资料外泄;美国货币监理署(OCC)在 2020 年 8 月开出 8000 万美元罚单。模型选得再对,给出去的范围过宽,一样出事。
认证 ≠ 授权:两件事,两套规矩
选型之外,还有一条更基础的划线:「能进去」是放行,「你是谁」和「你能做什么」是两件事。
这个划线在标准的分工里看得很清楚:NIST 的电子认证指南 SP 800-63 处理的是身份认证;属性、授权与访问控制由 SP 800-53 的 AC 家族(AC-3 访问执行) 单独覆盖。两套规范历来分开,就是因为它们是两个问题。
工程上的推论:不要因为「登录成功了」就默认「权限没问题」。 登录凭证证明「你是谁」,证明不了「你能动哪些数据」。把这两件事混在一张凭证里,改权限要等人重新登录,凭证泄露等于权限清单拱手送人。
Autional 的落地:三层并存
回到开头那张工单。Autional 的答案不是三选一,而是三层各答各的问题:
- 按岗位打底(RBAC):
rbac-service实现 NIST RBAC 的 Core + 层级继承(ParentID继承链,checkCircularHierarchy用 BFS 防环)+ 静态职责分离(ConflictPair冲突对,种子数据内置 3 对)。改一次角色,挂它的人一起变。 - 按条件收窄(ABAC):
abac_evaluator对表达式求值,采用 deny-override 语义——按岗位先判,角色放行的操作,再被条件层兜一层(比如时间窗、环境限制)。 - 按关系兜底(ReBAC):
rbac_relationships存 Zanzibar 风格的关系元组,micro-pkg/rebac提供 BFS 与 Expand——「这条数据归谁」交给它答。
配套的还有两条纪律:
- 默认给得少:新账号进来先给最小角色,要加权限走审批(PIM 即时角色),大权限不常驻。
- 凭证里不带权限:认证归
identity-service、授权归rbac-service,两个服务物理分开。role_checker.go里写得很直白——access token 不携带角色,角色按需解析。这意味着改权限立刻生效(不用等人换凭证),凭证泄露也泄露不出权限清单。
诚实边界:ABAC 要用的部门/组织信息在 tenant-service,我们的实现只保存引用(两套条件实现的语义统一仍是待办);动态职责分离(Dynamic SoD,即「两份角色可以先都拿着、但不许同一时刻一起用」)尚未实现——覆盖到的是「够用」,不是「全」。各系统具体落在哪一档、怎么混用,公开资料通常不全,选型时请以自己系统的实测为准。
常见误区
- 「更细的办法更安全」——错。规则配不好,再细也照样漏。
- 「三种得三选一」——错。现实里多半混着用:岗位打底、条件收窄、关系顶细节。
- 「名字唬人」——RBAC/ABAC/ReBAC 只是行话,本质就是三种问法。
- 「登录成功 = 有权限」——登录答「你是谁」,权限答「你能做什么」,两码事。
- 「权限给完就没事」——权限只增不减是常态;转岗、离职时不收回,旧权限会一直挂着。
- 「角色 = 头衔」——角色是「能做的事的打包」,不是「经理/总监」。
结语
下次再设权限,先别急着勾选框。先问自己一句:我要管的,是一类人、一堆条件,还是「这条到底归谁」?
问法定了,办法就定了。三套模型不是三种武器,而是三种问法——管权限,先看你在问哪种问题。
相关阅读
准备好给应用加上身份层了吗?
Autional 提供认证、组织、访问控制、审计与开发者 API —— 面向 AI 生成应用的身份层。