跳转至主要内容

RBAC、ABAC、ACL 与 ReBAC:如何选择访问控制模型

访问控制模型的区别只有一点:授权判定依据的是什么。

RBAC vs ABAC in short: RBAC grants permissions to roles and assigns roles to users, so it answers "what can editors do?" easily but cannot say "only their own documents" without a role per document. ABAC evaluates conditions on attributes of the user, the resource and the environment, so it handles ownership, department and time rules naturally but is harder to audit. Most applications use RBAC for features and add ABAC conditions for records; the last example on this page does both in one Casbin model.

模型判定依据规则示例
ACL(访问控制列表)用户本身alice 可以编辑 design.md
RBAC(基于角色)用户的角色编辑者可以编辑文档
ABAC(基于属性)用户、资源和上下文的属性所有者可以编辑自己的文档;同部门的人可以阅读
ReBAC(基于关系)用户与资源之间的关系只要是文件夹的查看者,就能阅读其中的文档
PBAC(基于策略)以策略形式存储的规则表达式策略行中写的任何条件

它们不是相互竞争的产品,而是编写规则的不同方式,实际系统往往混合使用。在 Casbin 中,每种模型都只需要几行模型配置,而且可以在不修改应用代码的情况下切换或组合。本页用每种模型表达同一个小例子,让区别更具体。

例子: 一个文档应用,只有一个文档 design.md,所有者是 alice。 alice 应该能编辑它,bob 应该能阅读它,其他人都没有访问权限。

ACL​

访问控制列表为每个用户列出他对每个对象能做什么。

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
p, alice, design.md, read
p, alice, design.md, edit
p, bob, design.md, read
  • 擅长: 小型系统和按对象共享(“把这个文件共享给 bob”)。每个判定都很容易解释。
  • 不擅长: 规模化。有 u 个用户和 o 个对象时,列表会增长到接近 u × o 行;有人换岗时,必须找到并修改他的所有行。

RBAC​

基于角色的访问控制在用户和权限之间加了一层角色。权限授予角色,用户被分配角色。

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
p, editor, design.md, read
p, editor, design.md, edit
p, viewer, design.md, read

g, alice, editor
g, bob, viewer
g, carol, viewer

给 carol 阅读权限只需要一行 g;她继承 viewer 能做的一切。角色还可以继承其他角色(g, editor, viewer),带域的 RBAC 让用户在不同租户中拥有不同角色。

  • 擅长: 权限跟随岗位职责的场景。易于审计(“编辑者能做什么?”“谁是管理员?”),入职或离职只需改角色。
  • 不擅长: 针对具体记录的规则。“作者可以编辑自己的文章”无法只用角色表达;硬要这么做会导致每条记录一个角色,也就是所谓的角色爆炸。

RBAC 与 ACL: ACL 就是没有角色的 RBAC。除非你真的只有寥寥几个用户,否则从 RBAC 开始,因为以后再加角色就意味着重写所有规则。

教程:Go、Node.js、NestJS、Python、Java、Rust、gRPC。

ABAC​

基于属性的访问控制根据用户(部门、密级)、资源(所有者、状态、敏感度)和环境(时间、IP 地址)的属性来评估条件。在 Casbin 中,把对象传给 Enforce(),在匹配器中读取它们的字段。

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub.Name == r.obj.Owner || (r.act == 'read' && r.sub.Department == r.obj.Department)

这里没有策略文件:alice 能编辑 design.md 是因为她是所有者,bob 能阅读是因为他在同一个部门。设计部的新文档无需修改任何规则,bob 就能阅读。

  • 擅长: 依赖记录本身或上下文的规则:所有权、部门、文档状态、工作时间、地区。一条规则就能代替很多角色授权。
  • 不擅长: 审计。“谁能阅读这个文档?”没有直接的答案,你必须对每个用户逐一评估条件。条件还需要相应的属性,也就是要在检查前先加载记录。

使用 eval() 模式 时,条件从模型移到策略行中,可以像其他规则一样在运行时添加和删除。

教程:Go、Node.js(Express)、Python(Flask)。

ReBAC​

基于关系的访问控制从关系推导权限:alice 是 design.md 的所有者,bob 是它的查看者,所有者可以编辑,查看者可以阅读。这是 Google Zanzibar 及其开源后继者背后的模型。

[request_definition]
r = sub, obj, act

[policy_definition]
p = relation, obj_type, act

[role_definition]
g = _, _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, r.obj, p.relation) && g2(r.obj, p.obj_type) && r.act == p.act
p, owner, doc, read
p, owner, doc, edit
p, viewer, doc, read

g, alice, design.md, owner
g, bob, design.md, viewer
g, bob, roadmap.md, owner

g2, design.md, doc
g2, roadmap.md, doc

bob 可以编辑他拥有的 roadmap.md,但只能阅读 design.md。 p 规则针对一类对象一次性描述每种关系允许什么,g 行记录谁与哪个对象有哪种关系。

  • 擅长: 共享与协作(文档、文件夹、项目、组织),尤其是权限沿“组织 → 文件夹 → 文档”这样的层级继承时。
  • 不擅长: 小型或扁平的系统,对它们来说这套机制过于复杂。每次创建或共享对象时都必须写入关系。

完整模型见 ReBAC;如果你在考虑专门的 Zanzibar 式服务,见 Casbin 与 OpenFGA 对比。

PBAC​

基于策略的访问控制与其说是一种独立的模型,不如说是编写其他模型的一种方式:规则本身就是以策略形式存储、在运行时求值的表达式。在 Casbin 中,这就是 ABAC 教程和 PBAC 页面中使用的 eval() 模式。它的价值在运维层面:安全或合规团队无需发布代码就能修改规则。

并排对比​

ACLRBACABACReBAC
规则写法用户–对象–操作角色–对象–操作,加上用户–角色基于属性的条件关系–类型–操作,加上用户–关系–对象
规则数量随什么增长用户数 × 对象数角色数 × 权限数不同条件的数量共享对象的数量
“alice 能做什么?”容易容易困难中等
“谁能阅读这个文档?”Easy容易困难容易
针对单条记录的规则(所有权)每条记录一行不发生角色爆炸就无法表达天然支持天然支持
上下文(时间、IP、状态)否否是需要额外的条件
典型用途小工具、文件共享管理后台、内部工具、大多数业务应用数据平台、受监管的数据、所有权规则协作应用、多级层级结构

如何选择​

  1. 从 RBAC 开始。 如果权限可以按岗位职责描述(“管理员”“编辑”“财务”),RBAC 是能扩展的最简单的模型,也最容易审计。
  2. 用 ABAC 条件处理所有权和上下文。 当你想要“只能是自己的”或“只能在工作时间”时,加条件而不是加更多角色。
  3. 当共享本身就是产品功能时,选择 ReBAC。 如果用户之间互相共享对象,访问权限沿文件夹、项目或组织继承,就直接对关系建模。
  4. 多租户用域。 如果同一个用户在不同组织中有不同角色,无论选择什么模型,都使用 带域的 RBAC。
  5. 只有在必要时才考虑强制访问控制模型。 BLP、Biba 和 LBAC 适用于有密级划分的环境,例如政府或国防。

结合 RBAC 和 ABAC​

大多数应用最终都会走到这一步:角色决定用户能使用哪些功能,属性再把范围缩小到他能操作的记录。在这个模型中,管理员可以编辑任何文档,作者只能编辑自己拥有的文档:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub.Name, p.sub) && r.obj.Type == p.obj && r.act == p.act && (p.sub == 'admin' || r.sub.Name == r.obj.Owner)
p, admin, doc, edit
p, author, doc, edit

g, erin, admin
g, alice, author
g, bob, author

对于 design.md(类型 doc,所有者 alice):alice 可以编辑,因为她是作者且是所有者;erin 可以编辑,因为她是管理员;bob 不可以:他是作者,但不是所有者。

常见问题​

ABAC 比 RBAC 更安全吗? 两者本身没有哪个更安全。 ABAC 能表达更细的规则,但判定更难审计;RBAC 更粗,但容易审查。安全来自规则与意图相符,并且能够验证它们确实相符。

可以先用 RBAC,以后再迁到 ABAC 吗? 可以。在 Casbin 中,模型是一个配置文件,应用调用的始终是同一个 Enforce() 方法,所以可以给匹配器加条件,或者像上面那样两者结合,而无需重写授权调用。

PBAC 放在哪里? PBAC 描述的更多是规则如何管理(作为运行时求值的策略数据),而不是规则依据什么。在每种模型中 Casbin 的策略都是数据,所以上面任何一种模型都可以这样管理。

Which libraries and platforms support both RBAC and ABAC? Casbin supports both, and their combination, in one model for Go, Java, Node.js, Python, .NET, Rust and other languages. Policy engines such as OPA and Cedar can express both as well, while Zanzibar-style services such as OpenFGA are built around ReBAC. Casbin vs. Alternatives compares them.

Casbin 支持所有这些模型吗? 支持,此外还支持 RBAC96、OrBAC、UCON,以及优先级和拒绝优先等策略。见 支持的模型,可以在 在线编辑器 中试用其中任何一种。

Comments are powered by giscus and GitHub Discussions. They load from giscus.app and GitHub only after you click the button below.