RBAC vs ABAC vs ACL vs ReBAC:选择访问控制模型访问控制模型的差异在于一点:授权决策基于什么。

RBAC vs ABAC 简述: RBAC 将权限授予角色,并将角色分配给用户,因此它能轻松回答“编辑者可以做什么?”,但如果没有为每个文档创建一个角色,就无法表达“仅限他们自己的文档”。ABAC 评估用户、资源和环境的属性条件,因此能自然地处理所有权、部门和时间规则,但更难审计。大多数应用程序使用 RBAC 进行功能权限管理,并添加 ABAC 条件来处理记录级权限;本页的最后一个示例在一个 Casbin Model 中同时实现了两者。

模型决策依据示例规则ACL (访问控制列表)用户alice 可以编辑 design.mdRBAC (基于角色)用户的角色编辑者可以编辑文档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, readp, alice, design.md, editp, 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, readp, editor, design.md, editp, viewer, design.md, readg, alice, editorg, bob, viewerg, carol, viewer

给 carol 授予读取权限只需要一行 g;她继承了 viewer 可以做的一切。角色也可以继承其他角色(g, editor, viewer),并且带域名的 RBAC允许用户在不同的租户中拥有不同的角色。

擅长: 遵循职能的权限。它易于审计(“编辑者可以做什么?”、“谁是管理员?”),而且入职或离职只是角色变更。

不擅长: 关于特定记录的规则。“作者可以编辑他们自己的文章”不能仅用角色来编写;强行尝试会导致每个记录一个角色,即所谓的角色爆炸。

RBAC vs ACL: ACL 是没有角色的 RBAC。除非你真的只有少量用户,否则应从 RBAC 开始,因为后来添加角色意味着重写每条规则。

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

ABAC​

基于属性的访问控制评估用户(部门、密级)、资源(所有者、状态、敏感度)和环境(时间、IP 地址)的属性条件。在 Casbin 中,你将对象传递给 Enforce() 并在 matcher 中读取其字段。

[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 with Express, Python with 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, readp, owner, doc, editp, viewer, doc, readg, alice, design.md, ownerg, bob, design.md, viewerg, bob, roadmap.md, ownerg2, design.md, docg2, roadmap.md, doc

bob 可以编辑他拥有的 roadmap.md,但只能读取 design.md。p 规则描述每种关系对某一类对象允许的一次操作,而 g 行记录谁与哪个对象具有哪种关系。

擅长: 共享和协作(文档、文件夹、项目、组织),特别是当权限通过层级结构(如 organization → folder → document)继承时。

不擅长: 小型或扁平系统,在这些系统中它显得过于复杂。每当创建或共享对象时都必须写入关系。

有关完整模型,请参阅 ReBAC;如果你正在考虑专用的 Zanzibar 风格服务,请参阅 Casbin vs. OpenFGA。

PBAC​

基于策略的访问控制与其说是一个独立的模型,不如说是编写其他模型的一种方式:规则本身作为策略存储并在运行时评估。在 Casbin 中,这就是 ABAC 教程和 PBAC 页面上使用的 eval() 模式。其价值在于运营层面:安全或合规团队可以在无需发布代码的情况下更改规则。

并列对比​

ACLRBACABACReBAC规则编写形式为user–object–actionrole–object–action,加上 user–role基于属性的条件relation–type–action,加上 user–relation–object规则数量随以下因素增长users × objectsroles × permissionsdistinct conditions 的数量shared objects 的数量"alice 能做什么?"容易容易困难中等"谁可以读取此文档?"容易容易困难容易单条记录规则(所有权)每条记录一行若不使用角色爆炸则无法表达自然支持自然支持上下文(时间、IP、状态)否否是仅通过额外条件支持典型用途小型工具、文件共享管理面板、内部工具、大多数业务应用数据平台、受监管数据、所有权规则协作应用、多级层级结构

如何选择​

**从 RBAC 开始。**如果权限可以通过职位功能描述(例如 "admins", "editors", "billing"),那么 RBAC 是最简单且可扩展的模型,也是最易于审计的。

**为所有权和上下文添加 ABAC 条件。**当你发现需要实现“仅限本人”或“仅限工作时间”等逻辑时,请添加条件而不是创建更多角色。

**当共享是产品核心时选择 ReBAC。**如果用户之间互相共享对象,并且访问权限通过文件夹、项目或组织继承,请直接对关系进行建模。

**使用域来实现多租户。**如果同一用户在不同组织中拥有不同角色,无论其他部分如何选择,请使用 带域的 RBAC。

仅在必要时考虑强制访问控制模型。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, editp, author, doc, editg, erin, adming, alice, authorg, bob, author

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

常见问题​

**ABAC 比 RBAC 更安全吗?**两者都没有固有的安全性优势。ABAC 可以表达更细粒度的规则,但其决策更难审计;RBAC 粒度较粗但易于审查。安全性来自于符合你意图的规则,以及能够验证这些规则确实如此的能力。

**我可以先从 RBAC 开始,之后迁移到 ABAC 吗?**可以。在 Casbin 中,模型是一个配置文件,应用程序调用相同的 Enforce() 方法,因此你可以在 matcher 中添加条件,或者如上所述结合两者,而无需重写授权调用。

**PBAC 处于什么位置?**PBAC 更多地描述了规则如何被管理(作为在运行时评估的策略数据),而不是规则基于什么。Casbin 中的策略在所有模型中都是数据,因此上述任何模型都可以以此方式管理。

**哪些库和平台同时支持 RBAC 和 ABAC?**Casbin 在 Go、Java、Node.js、Python、.NET、Rust 和其他语言中,在一个模型内支持 RBAC、ABAC 及其组合。像 OPA 和 Cedar 这样的策略引擎也能表达这两者,而像 OpenFGA 这样 Zanzibar 风格的服务则是围绕 ReBAC 构建的。Casbin 与其他方案的对比 对它们进行了比较。

**Casbin 支持所有这些模型吗?**是的,还支持其他模型,如 RBAC96、OrBAC、UCON、LBAC、Biba 完整性模型,以及优先级和拒绝优先策略。请参阅 支持的模型,并在 在线编辑器 中尝试其中任何一个。超级管理员 通过一个额外的 matcher 条件处理,而不是使用单独的模型。