授权的领域模型:从 RBAC、ABAC 到 Keycloak、Vault 的一张全景图

Posted on 日 14 6月 2026 in Tech

Abstract 授权的领域模型:从 RBAC、ABAC 到 Keycloak、Vault 的一张全景图
Authors Walter Fan
Category Cloud / Security
Status v1.0
Updated 2026-06-14
License CC-BY-NC-ND 4.0

一场选型会议上的鸡同鸭讲

前阵子参加一个授权方案的评审会,三个人三个主意。

A 说:"上 Keycloak,开源 IAM,登录、角色、权限一把梭。" B 说:"我们不是已经有 Vault 了吗?权限直接用 Vault 的 policy 管不就行了。" C 说:"这种细粒度的,得上 OPA / OpenFGA 才专业。"

听上去都挺有道理,但其实是在比三样不是同一回事的东西——Keycloak 主业是身份,Vault 主业是密钥,OPA/OpenFGA 才是冲着通用授权去的。把它们摆在一起选型,就像在"该买轿车、卡车还是自行车"之间投票,前提问错了。

所以今天我想换个角度:先别急着选工具,先把"授权"这件事建模清楚。 我的观点是——

授权(Authorization, AuthZ)首先是一个领域建模问题,其次才是一个选型问题。模型想清楚了,RBAC、ABAC、ReBAC 不过是同一个模型的几种切法;工具选型也会从"哪个最火"变成"哪个匹配我的关系形态和团队能力"。

这篇文章给你一张全景图:一个领域模型、五种经典切法、六个常见实现、一张选型表。读完你再开评审会,至少能把问题问对。

注:RBAC→OpenFGA(ReBAC)和 PERM/Casbin 这两块我之前各写过一篇深入的,本文是"全景 + 横向对比",细节会链到那两篇,不重复造轮子。


一、授权的领域模型:四元组 + 决策四件套

认证(Authentication)回答"你是谁",授权回答"你能不能干这件事"。我一直觉得:认证是楼门口那一道门,授权是楼里每一间房的锁。 门装一道就够,锁得一间间配,漏一间就是事故。

1.1 决策的核心:一个四元组

剥到最里面,任何一次授权判断,本质都是在回答一个布尔问题:

某个主体(Subject),能否对某个资源(Resource),执行某个操作(Action),在某个上下文(Context)下?

把它写成一个四元组:

allow? = decide(Subject, Resource, Action, Context)
  • Subject(主体):谁。用户、服务账号、API key、设备……带着一身属性(部门、等级、所属租户)。
  • Resource(资源):对什么。一篇文档、一个订单、一条日志、一个 K8s namespace。资源也有属性(owner、敏感级别、所属项目)。
  • Action(操作):做什么。读、写、删、审批、转账。
  • Context(上下文):什么条件下。时间、IP、设备可信度、风控分、是否在 VPN 内。

不同授权模型的差别,说白了就是它们主要拿这四个里的哪几个来做决策、怎么组织规则。这是后面所有对比的"统一坐标系",记住它。

1.2 决策的架构:PEP / PDP / PAP / PIP

光有四元组还不够。在工程上,"判断"和"执行"必须分开,否则授权逻辑又会像狗皮膏药一样贴满业务代码。经典的 XACML 模型把授权系统拆成四个角色,我觉得这是授权领域最值钱的一张图:

角色 全称 干什么 通俗比喻
PEP Policy Enforcement Point 拦截请求、执行决策结果 门口的保安
PDP Policy Decision Point 根据策略算出 allow / deny 拿着规章的裁决者
PAP Policy Administration Point 管理、编辑策略 制定规章的管理处
PIP Policy Information Point 补充决策需要的属性 查档案的资料室

一次请求的旅程是这样的:

请求 ──▶ PEP(保安拦下) ──▶ PDP(裁决者查规章)
                              │
                              ├─ 缺信息? ──▶ PIP(资料室补属性)
                              ▼
                          allow / deny ──▶ PEP 放行 or 拒绝

为什么这套分层重要?因为它决定了你的授权能不能解耦

  • PEP 和 PDP 分开,业务代码里就只剩一行 if !allowed { return 403 },决策逻辑搬走了。
  • PAP 独立出来,产品、安全、运维不用改代码就能调策略。
  • PIP 独立出来,决策需要的属性(用户等级、资源 owner)可以现拉,不必塞进每个请求。

你后面看到的所有工具,本质都是在这张图的不同位置上发力:Casbin 是个嵌进进程里的 PDP,OPA 是个独立部署的 PDP,Keycloak 把 PAP + PDP 打包成了一个带 UI 的服务……定位差异,从这里就分叉了。


二、五种经典模型:同一个四元组的不同切法

明确了坐标系,再看那些缩写就不晕了。它们的区别,就是"主要用四元组里的哪几个、规则怎么组织"。

2.1 ACL:直接列名单

最古老的 Access Control List:一张表,逐条写"谁能对谁做什么"。

alice  →  /report.pdf  →  read
bob    →  /report.pdf  →  write
  • 切法:Subject × Resource × Action 直接枚举。
  • 优点:直观,5 条规则以内无敌。
  • 死穴:规则随用户和资源数量相乘膨胀,1000 用户 × 1000 资源能把人写哭。

2.2 RBAC:在中间加一层"角色"

Role-Based Access Control 的精髓,是在 Subject 和 Permission 之间插一个角色做缓冲:

User ── Role ── Permission(Action × Resource)

加人只管"给什么角色",加权限只管"角色能干啥",两边解耦。这是企业系统几十年的主力,简单、标准、可审计。

它的边界在哪?一旦出现"这份文档只共享给这一个人"这种实例级、动态的权限,RBAC 就开始角色爆炸(editor_of_doc_123……)。这块我在《从 RBAC 到 OpenFGA》里展开过。

2.3 ABAC:用属性算规则

Attribute-Based Access Control 不枚举名单,而是写规则,让四元组里的属性参与运算:

allow if  subject.dept == resource.dept
      and subject.level >= 3
      and context.time in 工作时间
  • 切法:把 Subject / Resource / Context 的属性都拉进来当变量。
  • 优点:表达力强,天然支持上下文(时间、IP、风控)。
  • 死穴:规则一多就难审计——"到底谁能访问这份文件"不再能一眼看出,得把规则跑一遍才知道。XACML 是 ABAC 的经典标准,但 XML 写起来劝退,所以现在大家更爱用 Rego、Cedar 这类新语言。

2.4 ReBAC:以"关系"为中心

Relationship-Based Access Control 是 Google Zanzibar 论文带火的思路,把权限建模成对象之间的关系图

doc:123#owner@user:alice
folder:x#viewer@group:eng#member
doc:123#parent@folder:x        // 文档继承文件夹的权限

"alice 能不能看 doc:123"变成一道图可达性问题。它特别擅长 RBAC 头疼的场景:层级继承、动态共享、"我朋友的朋友"。OpenFGA、SpiceDB 都是它的开源实现,细节见上面那篇 OpenFGA 文章。

2.5 PBAC / PoLP:策略即代码,最小够用

Policy-Based Access Control 更像一种统筹视角:把上面几种揉进一份集中管理的策略里,用专门的策略语言(Rego、Cedar)描述,让 RBAC 和 ABAC 在同一份策略里共存。配套的是 PoLP(Principle of Least Privilege,最小权限原则)——默认拒绝,只授必要的权。

把五种切法放一张表上对照:

模型 主要靠四元组的哪部分 一句话 最擅长 最头疼
ACL Subject × Resource 直接列名单 极简系统 规模膨胀
RBAC Subject→Role 加一层角色缓冲 企业固定权限 实例级/动态共享
ABAC 全属性 + Context 用属性写规则 上下文相关、动态条件 可审计性差
ReBAC Subject↔Resource 关系 权限是一张关系图 层级继承、动态共享 关系建模有学习成本
PBAC 策略统筹以上各种 策略即代码 跨系统统一治理 需要策略平台与规范

它们不是替代关系,是叠加关系。 真实系统里,最常见的是 "RBAC 打底 + ABAC 补条件 + 关键资源上 ReBAC"。别指望一个模型包打天下。


三、六个常见实现:先认清定位,再谈优劣

回到开头那场鸡同鸭讲。下面这几个名字经常被摆在一起 PK,但它们根本不在一个赛道。先认定位,再比参数。

3.1 Keycloak:身份为主,授权为辅

Keycloak 是 Red Hat 开源、现已进 CNCF 孵化的 IAM(身份与访问管理)平台。它的主业是认证:OIDC / SAML / OAuth2、单点登录、社交登录、用户联邦,这些是它的看家本领。

授权方面,Keycloak 提供两层:

  • 粗粒度:Realm/Client 角色 + 用户组,标准 RBAC,签发到 token 里(roles claim),业务系统拿 token 自己判断。这是 90% 团队实际用到的部分。
  • 细粒度:它还有一个叫 Authorization Services 的模块,支持资源级、基于策略(角色/用户/时间/聚合等)的权限,底层用 UMA 2.0。能力不弱,但配置偏重,用的人相对少。

一句话定位:你需要的是"登录 + 发身份令牌 + 基础角色",Keycloak 是省心的一站式答案;指望它做复杂的业务内细粒度授权,会感觉杀鸡用了牛刀又不太顺手。

3.2 HashiCorp Vault:它管的是"密钥",不是你的"业务授权"

这是最容易被误用的一个。HashiCorp Vault 的本职是机密管理(secrets management)——存数据库密码、签发动态凭证、做加密即服务。

Vault 当然有授权机制,但它授权的对象是 Vault 自己的资源(路径上的 secret),模型是路径 + capability 的 ACL/能力模型,策略用 HCL 写:

# 这条策略:允许读 secret/data/app/* 下的密钥
path "secret/data/app/*" {
  capabilities = ["read", "list"]
}

path "secret/data/prod/*" {
  capabilities = ["deny"]
}

capability 就那么几个:create / read / update / delete / list / sudo / deny

划重点:Vault 的 policy 是用来管"谁能取哪个密钥"的,不是给你的业务系统做"谁能审批这张订单"那种通用授权的。开头 B 同学说"用 Vault 的 policy 管权限",方向就错了——那是把保险柜的钥匙管理系统,硬拿来当整栋楼的门禁。各管一摊,别混用。

3.3 OPA / Casbin / OpenFGA / Cedar:真正的授权引擎

这四个才是冲着"通用授权决策(PDP)"去的,但各有侧重:

实现 模型取向 部署形态 策略语言 最适合
Casbin PERM 元模型,可配成 ACL/RBAC/ABAC 进程内库(多语言) .conf + 策略表 单体/单服务内的权限,微秒级、零运维
OPA 通用策略(偏 ABAC/PBAC) 独立进程 / sidecar / WASM Rego 跨服务统一策略面、K8s 准入、网关鉴权
OpenFGA / SpiceDB ReBAC(Zanzibar) 独立服务 关系建模 DSL 层级继承、动态共享、社交图谱式权限
Cedar RBAC + ABAC 融合 库 / Amazon Verified Permissions Cedar 语言 想要可读策略 + 形式化验证、AWS 生态

Casbin 和 OPA 的详细对比,我在《PERM 模型与 Casbin》里掰开讲过;ReBAC 看 OpenFGA 那篇。Cedar 是 AWS 2023 年开源的策略语言,卖点是策略可读 + 用自动推理做形式化分析,被 Amazon Verified Permissions 采用,生态较新但值得关注。

把这一节的定位总结成一句话:

Keycloak 给你身份和 token,Vault 给你密钥,OPA/Casbin/OpenFGA/Cedar 给你授权决策。 它们经常配合使用,而不是二选一。

一个常见的健康组合是:Keycloak 管登录发 token → 业务系统当 PEP → OPA/Casbin/OpenFGA 当 PDP 做细粒度决策 → Vault 在后台管密钥。各司其职,互不抢饭碗。


四、选型决策:两步走

别再问"哪个最好"。授权选型我只看两件事:关系形态团队能力 + 部署形态

第一步:按"权限的关系形态"选模型

权限规则 5 条以内,永远不变?        → 一段 if-else / ACL,别折腾
权限按"岗位/角色"组织,相对固定?     → RBAC 打底
要看时间、IP、风控、属性等条件?      → 加 ABAC
存在"层级继承 / 实例级动态共享"?     → 关键资源上 ReBAC
要跨多个系统统一治理策略?           → 上 PBAC(策略平台 + Rego/Cedar)

第二步:按"团队能力 + 部署形态"选工具

你的处境 推荐 理由
单个服务,权限跟业务紧耦合 Casbin 进程内、微秒级、零运维
多服务/多语言,要统一策略面 OPA sidecar 架构,跨语言
层级继承、动态共享是核心需求 OpenFGA / SpiceDB Zanzibar 专治这病
只想要登录 + 基础角色 Keycloak 一站式 IAM,省事
要管密钥/凭证(不是业务授权) Vault 专业机密管理
重 AWS、想要可验证策略 Cedar / AVP 形式化分析 + 生态

一条朴素的经验:从 RBAC 起步,等真痛了再加 ABAC 条件、再上 ReBAC,最后才考虑策略平台。 没几个团队是一上来就需要 Zanzibar 的,过早上重武器,运维成本会反噬你。


五、四个反复踩的坑

用授权这些年,下面这几个坑我和同事反复掉进去过:

坑 1:把 PEP 和 PDP 焊死在一起。 授权判断散落在几十个 handler 里,加一个角色得改三十处 if。先把"判断"抽出去(哪怕只是抽成一个函数),后面换引擎才不至于伤筋动骨。

坑 2:默认放行。 安全的默认值永远是 deny。新加的路由、漏配的资源,必须落到"拒绝"而不是"放行"。很多越权漏洞(IDOR 之类)的根因,就是默认值反了。

坑 3:把工具用错赛道。 拿 Vault 当业务授权引擎、指望 Keycloak 搞定一切细粒度权限、为了两个角色硬上 OpenFGA——都是定位没认清。先认定位,再谈优劣。

坑 4:策略写成代码的镜像。 给每个 API 写一条策略 p, alice, /api/v1/users/:id, GET,本质还是把 if-else 搬进了配置文件,白白丢了抽象。策略要按业务概念组织,不是按 URL 切片。


收束:先建模,再选型

回到那场评审会。后来我们没有马上投票选工具,而是先在白板上画了那个四元组和 PEP/PDP/PAP/PIP 的分层图,然后问了三个问题:

  1. 我们的权限主要是"按角色"还是"按关系"?——答案是角色为主,少数资源要动态共享。
  2. 判断逻辑要不要跨服务统一?——暂时不用,先收敛在主服务里。
  3. 谁来改策略?——产品和安全也要能改。

问完,结论自己就浮出来了:Keycloak 管登录发 token,主服务里用 Casbin 做 RBAC 打底、给少数共享场景留 ReBAC 的升级口子,Vault 继续安心管它的密钥。 没有谁取代谁,各回各家。

授权这个领域,最难的从来不是规则复杂,而是规则会变、而且常常变得没道理。一个好的领域模型,作用就是把"会变的部分"关进一个可控、可审计、可热更新的地方,让代码层稳如老狗。

认证是一道门,授权是每一把锁;模型是锁的图纸,工具只是锁的牌子。图纸对了,换牌子不疼。

总结脑图

@startmindmap authz_domain_model_mindmap
* 授权领域模型
** 核心四元组
*** Subject 主体
*** Resource 资源
*** Action 操作
*** Context 上下文
** 决策四件套
*** PEP 执行点(保安)
*** PDP 决策点(裁决者)
*** PAP 管理点(管理处)
*** PIP 信息点(资料室)
** 五种切法
*** ACL 列名单
*** RBAC 加角色层
*** ABAC 用属性
*** ReBAC 关系图
*** PBAC 策略统筹
** 实现定位
*** Keycloak 管身份
*** Vault 管密钥
*** Casbin 进程内PDP
*** OPA 独立PDP
*** OpenFGA ReBAC
*** Cedar RBAC+ABAC
** 选型两步
*** 先看关系形态选模型
*** 再看团队/部署选工具
** 避坑
*** PEP/PDP 要解耦
*** 默认 deny
*** 别用错赛道
*** 策略按业务组织
@endmindmap

授权领域模型脑图

行动清单

  1. 给你现有系统画一遍四元组:当前授权判断到底用了 Subject/Resource/Action/Context 里的哪几个?
  2. 检查 PEP 和 PDP 是否解耦:授权逻辑能不能一处修改、全局生效?
  3. 把默认值审一遍:新增路由、漏配资源,落到 allow 还是 deny?
  4. 把团队在用的"授权工具"按定位归类:哪个管身份、哪个管密钥、哪个真在做授权决策?有没有用错赛道?
  5. 画一张属于你们的选型决策表,下次评审会直接拿出来,省掉鸡同鸭讲。

扩展阅读


本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。