权限设计怎么做?6 种模型从原理到实战全解析
本文系统梳理了六种主流权限控制模型(ACL、RBAC、ABAC、PBAC、DAC、MAC),从核心思路、优缺点到适用场景逐一剖析,并给出实际项目中的选型建议和混合模型实践。
写在前面
几乎每一个稍具规模的后台系统都绕不开权限控制——谁能看到什么数据、谁能执行什么操作,这些规则直接决定了系统的安全性和可用性。但权限控制远不止"加个权限字段"那么简单,不同的业务场景需要不同的权限模型来支撑。选错了模型,轻则管理成本飙升,重则留下安全漏洞。
我在实际项目中接触过几种权限模型,踩过一些坑,也做过一些取舍。这篇文章把主流的权限控制模型梳理一遍,希望对正在做权限设计的同学有所帮助。
权限控制的基本概念
在展开各种模型之前,先统一几个核心术语:
- 主体(Subject):发起访问请求的实体,通常是用户,也可以是服务账号、设备等
- 客体/资源(Object/Resource):被保护的对象,比如文件、接口、数据、菜单等
- 操作(Action):主体对客体执行的行为,如读取、写入、删除、执行
- 权限(Permission):主体是否被允许在某种条件下对某种资源执行某种操作
- 策略(Policy):一组规则声明,定义在什么条件下允许或拒绝访问
理解了这些概念,我们来看看不同的权限模型是如何组织主体、资源和操作之间的关系的。
一、ACL:访问控制列表——最直觉的"谁可以干什么"
核心思路
ACL(Access Control List)是最基础、最直觉的权限模型。它的核心逻辑非常简单:每个资源维护一份"访问者清单",明确记录哪些主体可以对它执行哪些操作。
用公式表达就是:
1 | 资源 → [(主体, 操作), (主体, 操作), ...] |
举个例子:一个文件的 ACL 可能长这样:
1 | 文件A: |
这其实就是很多开发者最初做权限系统的方式——直接在用户和权限之间建立关联。用户量少的时候,这种方式简单直接,非常有效。
优点
- 直观易懂:权限关系一目了然,排查问题时直接看资源的 ACL 清单就行
- 粒度极细:可以精确到单个资源的单个操作,想给谁什么权限就给什么权限
- 实现简单:不需要引入角色、策略等中间层,数据库里一张关联表就能搞定
- 灵活度高:可以对任意用户做任意粒度的权限调整,不受任何框架约束
缺点
- 管理成本随规模爆炸:当用户和资源数量增长时,权限记录会急剧膨胀。1000 个用户 × 1000 个资源 = 最多 1,000,000 条权限记录,维护起来极其痛苦
- 无法批量管理:新增一个员工,需要逐个资源添加权限;员工调岗,需要逐个资源修改权限,极易遗漏
- 缺乏抽象能力:无法表达"所有经理都能查看财务报表"这样的规则,只能逐个经理添加
- 权限冗余严重:多个资源的授权规则重复时,无法复用,只能重复配置
适用场景
- 用户量少(几十人以内)、资源数量有限的内部系统
- 需要对单个资源做精细化权限控制的场景,如文档协作平台(Notion、Trello 的单页面权限)
- 操作系统文件权限(Linux 的
chmod就是 ACL 的典型实现) - 临时授权场景,如临时给某人开放某个文件的编辑权限
个人体会
ACL 是我最早接触的权限模型,也是很多人做第一个权限系统时的选择。小项目用起来确实爽——想给谁权限就给谁,没有任何中间层的阻碍。但一旦用户超过一定规模,管理就会变成噩梦。我曾经在一个内部系统中用 ACL 方式管理权限,后来人员变动频繁,每次调岗都要手动改一堆权限,还经常改漏,最后不得不重构为 RBAC。
二、RBAC:基于角色的访问控制——企业级权限的标配
核心思路
RBAC(Role-Based Access Control)是目前应用最广泛的权限模型。它的核心思想是引入"角色"作为用户和权限之间的中间层:先把权限分配给角色,再把角色分配给用户。用户通过关联角色间接获得权限,实现"用户 → 角色 → 权限"的三层映射。
1 | 用户 → 角色 → 权限 |
举个例子:
1 | 角色定义: |
RBAC 还可以进一步演进:
- RBAC0:基础模型,用户-角色-权限三层结构
- RBAC1:增加角色继承,比如"技术总监"自动继承"开发工程师"的所有权限
- RBAC2:增加职责分离(SoD),比如"会计"和"出纳"角色互斥,同一用户不能同时拥有
优点
- 批量管理极其方便:新员工入职只需赋予对应角色,角色下的所有权限自动生效。1000 个新员工入职,也只需要分配角色即可
- 批量修改同样方便:需要调整某类人员的权限时,只需修改角色对应的权限,所有关联用户自动生效,不会遗漏
- 结构清晰:权限关系通过角色组织,一目了然,便于审计和合规
- 职责分离:RBAC2 支持互斥角色,防止权限集中带来的风险
- 完美匹配企业组织架构:角色天然对应职位/岗位,与企业科层制高度契合
缺点
- 难以精细化调控:角色的粒度是固定的,无法表达"张三虽然是经理,但不能看某个特定报表"这样的需求。要么给角色加权限(影响所有经理),要么单独处理(又回到了 ACL 的痛点)
- 角色爆炸问题:当权限需求复杂多变时,角色数量会急剧膨胀。比如矩阵式组织中,一个员工同时属于项目 A 和部门 B,就需要创建 "项目A-经理"、"项目B-经理"、"部门C-经理" 等大量组合角色,角色可能达到上百个,管理反而变得困难
- 静态性:无法处理动态条件,比如"只有工作时间才能访问"、"临时借调期间可以查看"这类场景
- 灵活度低:一旦权限需求超出角色模型的表达能力,就只能通过创建更多角色来弥补,陷入角色爆炸的恶性循环
适用场景
- 企业后台管理系统(ERP、CRM、HR 系统等)
- 组织架构相对稳定、权限变化不频繁的系统
- 需要批量管理用户权限的场景
- 对合规审计有要求的系统
个人体会
RBAC 是我目前用得最多的权限模型,大部分企业级项目都在用。它的优势在组织架构稳定时非常明显——新增角色、调整权限都很方便。但我也遇到过角色爆炸的问题:一个项目里因为权限需求太细,角色从最初的 10 个膨胀到了 80 多个,每次新增功能都要纠结是新建角色还是修改现有角色,管理成本反而比 ACL 还高。后来我的做法是在 RBAC 基础上引入数据权限(行级过滤),一定程度上缓解了角色爆炸的问题。
三、ABAC:基于属性的访问控制——动态灵活的权限引擎
核心思路
ABAC(Attribute-Based Access Control)不再依赖固定的角色或列表,而是根据主体、资源、环境、操作等多个维度的属性动态计算权限。
这么说可能还是有点抽象,我们换一种方式理解:在 RBAC 中,权限是"你是经理,所以你能看报表",这是一个静态的、非黑即白的判断;而在 ABAC 中,权限是"你是经理,并且你在工作时间,并且你从内网访问,并且这份报表属于你管辖的部门,所以你能看"——权限取决于多个条件是否同时满足。
ABAC 涉及四维属性:
- 主体属性(谁在访问):用户的部门、职级、项目组成员标签等
- 资源属性(访问什么):数据的密级、所属业务线、所属区域等
- 环境属性(在什么条件下访问):访问时间、网络位置(内网/外网)、设备安全状态等
- 操作属性(做什么操作):读取、写入、删除、导出等(不同操作可以有不同的策略)
伪代码示例
下面用一个简化的权限判断函数来展示 ABAC 的工作方式:
1 | def check_permission(user, resource, action, environment): |
再来看一个更贴近实际的场景——一个多租户 SaaS 平台的权限判断:
1 | def check_saaS_permission(tenant, user, resource, action, env): |
从上面的伪代码可以看出,ABAC 的核心就是把权限判断变成一组条件规则的组合。每条规则检查一个或多个属性,所有规则都通过才允许访问。这比 RBAC 的"角色决定一切"要灵活得多——你不需要为"工作日内网财务经理"这种组合创建角色,只需要写几条规则就行。
优点
- 极高的灵活性:可以表达任意复杂的权限规则,支持多维度组合判断
- 动态授权:权限不是静态绑定的,而是根据实时属性动态计算,环境变化时权限自动调整
- 解决角色爆炸:不需要为每种权限组合创建角色,通过属性组合自然表达
- 上下文感知:可以结合时间、地点、设备等环境因素做权限决策,比如检测到异地登录自动降级权限
- 数据权限天然支持:通过资源属性可以轻松实现"只能查看本大区销售数据"这类行级权限
缺点
- 配置复杂:属性定义、策略编写、规则组合都需要专业能力,学习曲线陡峭
- 性能开销:每次访问都需要实时计算多维度属性,对系统性能有影响,缓存策略至关重要
- 调试困难:权限被拒绝时,需要追溯是哪个属性不匹配导致的,可观测性要求高
- 策略测试困难:属性组合的排列组合非常多,很难覆盖所有场景,容易出现意料之外的权限结果
- 理解成本高:相比 ACL 和 RBAC,ABAC 的权限规则不够直观,非技术人员很难理解
适用场景
- 多租户 SaaS 平台,需要根据租户属性动态控制权限
- 权限规则复杂、需要条件判断的系统,如"只有工作日工作时间才能访问"
- 需要动态权限调整的场景,如临时借调、风险自适应
- 对数据权限有精细化要求的系统,如"只能查看本部门的数据"
- 云原生环境下的动态权限控制
四、PBAC:基于策略的访问控制——权限即代码
核心思路
PBAC(Policy-Based Access Control)的核心思想是把权限规则写成一段"策略代码",而不是存在数据库里。这些策略代码用专门的声明式语言编写,可以像普通代码一样放进 Git 做版本管理、Code Review、自动化测试。
这么说可能还是有点抽象,我们来对比一下传统方式和 PBAC 方式的区别:
传统方式(权限规则存在数据库):
- 管理员在后台界面勾选"经理角色可以查看报表"
- 这条规则存在数据库的权限表里
- 要改权限?去后台界面重新勾选
- 谁改的?什么时候改的?之前的规则是什么?——不知道,数据库里没有历史记录
PBAC 方式(权限规则写成代码):
- 开发者写一段策略代码,提交到 Git
- Code Review 通过后部署生效
- 要改权限?修改代码,提交 PR,Review,部署
- 谁改的?什么时候改的?之前的规则是什么?——Git 里清清楚楚
架构:PDP 和 PEP 是怎么配合的
PBAC 的运行架构分为两个核心组件,它们各司其职:
- PEP(Policy Enforcement Point,策略执行点):部署在业务服务里,负责拦截用户的请求。它自己不做权限判断,只做一件事——把请求信息打包,发给 PDP 问"这个请求允不允许",然后根据 PDP 的回答执行允许或拒绝
- PDP(Policy Decision Point,策略决策点):一个独立的策略引擎服务,负责接收 PEP 的查询请求,根据策略代码计算权限结果,返回"允许"或"拒绝"
整个流程如下:
1 | 用户发起请求 |
为什么要分成 PDP 和 PEP 两个组件?因为决策和执行解耦带来了几个好处:
- 所有业务服务共享同一套策略,权限规则一致
- 策略变更只需要更新 PDP,不用改业务代码
- PDP 可以独立扩展和部署,不影响业务服务
策略代码长什么样
PBAC 使用专门的策略语言来编写权限规则,最常见的是 OPA 的 Rego 语言。下面看一个具体的例子:
1 | # 文件:finance_policy.rego |
当 PEP 发来一个查询时,PDP 会把请求信息作为 input 传入,然后逐条评估策略规则。如果某条规则匹配成功,allow 就变为 true。
PEP 发给 PDP 的查询请求大概长这样:
1 | { |
PDP 返回的结果:
1 | { |
策略也可以写测试
PBAC 的一大优势是策略代码可以像普通代码一样写单元测试:
1 | # 文件:finance_policy_test.rego |
运行测试:opa test . 就能验证策略逻辑是否正确,这在传统权限管理中是很难做到的。
PBAC 与 ABAC 的关键区别
PBAC 和 ABAC 看起来都能做灵活的权限判断,但它们的侧重点不同:
| 维度 | ABAC | PBAC |
|---|---|---|
| 表达形式 | 属性键值对 + 规则引擎 | 领域特定语言(DSL)写策略代码 |
| 版本控制 | 存在数据库,难以追溯 | Git 管理,完整变更历史 |
| 测试能力 | 黑盒测试 | 单元测试、策略模拟 |
| 复用性 | 规则与应用耦合 | 策略独立,可跨服务复用 |
| 审计能力 | 需要额外实现 | 策略变更可追溯、可回滚 |
简单来说,ABAC 侧重的是"用什么方式判断权限"(用属性),PBAC 侧重的是"用什么方式管理权限规则"(用代码)。实际上 PBAC 内部完全可以使用 ABAC 的属性判断逻辑,只不过这些逻辑是用策略代码来表达的,而不是散落在数据库或配置文件里。
优点
- 策略即代码:权限规则像代码一样管理,支持版本控制、Code Review、回滚
- 可测试:策略可以编写单元测试,确保权限逻辑的正确性
- 决策与执行解耦:PDP 独立部署,PEP 只负责查询和执行,架构清晰
- 集中管理:所有策略集中在一个地方,便于统一管控和审计
- 高性能:可以采用 Sidecar 模式,每个服务本地部署策略引擎,毫秒级响应
缺点
- 策略抽象门槛高:需要学习策略语言(如 Rego),对开发人员有额外要求
- 不利于非开发人员维护:策略以代码形式存在,产品经理、运维人员难以直接参与
- 系统复杂度增加:引入了 PDP、PEP 等额外组件,部署和运维成本上升
- 过度设计的风险:对于简单的权限需求,PBAC 可能是杀鸡用牛刀
适用场景
- 多租户系统,需要集中管控权限策略
- 零信任架构、安全平台
- 微服务架构下需要统一权限决策的系统
- 对合规审计要求极高的系统(金融、医疗等)
- 权限规则需要频繁变更且需要可追溯的场景
五、DAC:自主访问控制——资源所有者说了算
核心思路
DAC(Discretionary Access Control)的核心特点是资源的所有者可以自主决定谁能访问自己的资源,并可以将权限授予他人。"自主"是 DAC 与 ACL 最关键的区别——ACL 只是记录谁可以访问,而 DAC 允许权限的持有者将权限再分配给其他用户。
举个例子:张三创建了一个文档,他可以自主决定让李四也能编辑这个文档,而李四又可以决定让王五也能查看。权限可以像接力一样传递下去。
优点
- 灵活性高:资源所有者可以随时调整权限,无需管理员介入
- 用户理解成本低:逻辑简单,"我的东西我决定谁能用"
- 授权便捷:适合需要频繁共享和协作的场景
缺点
- 无集中管控:权限分散在各个资源所有者手中,管理员难以全局管控
- 易误授权:权限可以传递,可能导致权限扩散到不可控的范围
- 安全风险高:一旦某个用户的账号被盗,攻击者可以访问该用户拥有的所有资源,并进一步扩散权限
- 审计困难:权限变更分散,难以追踪完整的权限变更链路
适用场景
- 文件共享系统(如百度网盘的文件分享)
- 操作系统文件层权限(Linux 文件系统的 owner 机制就是 DAC 的实现)
- 协作平台中的个人资源管理
- 对安全性要求不高、强调便捷共享的场景
六、MAC:强制访问控制——安全至上的铁律
核心思路
MAC(Mandatory Access Control)是最严格的权限模型,系统对资源和用户打上安全标签,权限强制遵守安全等级策略,任何个人都无法修改。权限决策完全由系统规则驱动,不依赖用户的主观判断。
MAC 的核心机制是安全级别:每个用户有一个安全许可级别(如绝密、机密、秘密、公开),每个资源也有一个安全分类级别。系统根据两条铁律强制执行访问控制:
- 向下读(No Read Up):用户只能读取安全级别等于或低于自己许可级别的资源。也就是说,你不能读取比你许可级别更高的东西
- 向上写(No Write Down):用户只能写入安全级别等于或高于自己许可级别的资源。也就是说,你不能往比你许可级别更低的地方写东西
为什么要这样设计? 这两条规则是为了防止两种信息泄露方式:
- **"向下读"防止的是"越级窥探"**:如果一个"秘密"级别的用户能读取"绝密"文件,那机密信息就泄露了。所以必须禁止低级别用户读取高级别资源
- **"向上写"防止的是"故意泄密"**:这是很多人容易忽略的一点。如果一个"绝密"级别的用户能把内容写到"公开"级别的文件里,那他就可以把绝密信息复制到公开文件中,相当于把机密信息"降级"泄露出去。所以必须禁止高级别用户往低级别资源写东西
用一个具体的例子来说明:
1 | 安全级别从高到低:绝密 > 机密 > 秘密 > 公开 |
这样一来,信息只能"向上流动"(从低级别到高级别),永远不能"向下流动"(从高级别到低级别),从而保证了机密信息不会泄露到低安全等级的区域。
优点
- 安全性极高:权限由系统强制执行,不存在误授权或权限扩散的风险
- 不依赖用户行为:即使资源所有者也无法修改权限规则,杜绝了人为失误
- 符合合规要求:军事、政府等高安全等级环境的标准要求
缺点
- 灵活性极差:安全等级和规则一旦设定就很难调整,无法适应快速变化的业务需求
- 不适用于业务系统:绝大多数业务系统需要灵活的权限管理,MAC 的刚性约束会严重阻碍业务
- 管理复杂:安全标签的维护和分级需要专业人员,成本高
- 用户体验差:严格的限制可能导致正常工作流程受阻
适用场景
- 军事系统、政府机密系统
- 金融核心平台(交易系统、清算系统)
- 对安全性要求极高、可以牺牲灵活性的场景
- 需要满足特定安全合规标准(如等保四级以上)的系统
模型对比速览
| 模型 | 控制方式 | 粒度 | 灵活性 | 管理难度 | 典型场景 |
|---|---|---|---|---|---|
| ACL | 资源挂权限清单 | 极细 | 高 | 高(规模大时) | 文档协作、小型系统 |
| RBAC | 角色分权 | 中等 | 中 | 低 | 企业后台、ERP/HR |
| ABAC | 属性组合判断 | 细粒度 | 极高 | 高 | SaaS 动态权限、云平台 |
| PBAC | 策略语言 | 任意 | 极高 | 极高 | 零信任、合规系统 |
| DAC | 所有者自主控制 | 简单 | 高 | 低 | 文件系统、共享平台 |
| MAC | 安全标签强制 | 粗粒度 | 低 | 高 | 军事、政府、金融核心 |
混合模型实践
在实际项目中,单一模型往往难以满足所有需求,组合使用才是更常见的做法:
RBAC + ACL
用 RBAC 管理基础权限结构(角色分配),用 ACL 处理个别资源的精细化授权。比如:大部分权限通过角色管理,但某个敏感文档需要单独控制谁能访问,就用 ACL 在该资源上做例外处理。
这是最常见的组合方式,很多框架(如 Spring Security)天然支持这种模式。
RBAC + ABAC
用 RBAC 分配基础权限(角色决定能访问哪些模块),用 ABAC 控制动态限制(属性决定在什么条件下可以访问)。比如:"经理角色可以查看报表"是 RBAC,"但只有工作日工作时间从内网访问时才能查看"是 ABAC。
这种组合既保留了 RBAC 的管理简便性,又获得了 ABAC 的动态灵活性,是当前企业系统的主流趋势。
PBAC + ABAC + RBAC
在大型中台或多租户系统中,用 PBAC 作为统一的策略管理层,RBAC 管理基础角色结构,ABAC 处理动态属性判断。策略引擎(如 OPA、Casbin)作为 PDP 统一决策,各服务作为 PEP 执行。
这种组合适合架构复杂、权限需求多变的大型系统,但引入的复杂度也很高,需要团队有足够的技术能力来驾驭。
选型建议
最后,给一个简化的选型思路:
- 系统角色稳定、权限变化不多 → 选 RBAC
- 有资源级差异访问需求 → RBAC + ACL
- 需要动态/条件型权限 → 引入 ABAC
- 需要集中可审计的策略管理 → 上 PBAC
- 强调便捷共享、用户自主 → DAC
- 安全等级要求极高 → MAC
- 业务复杂、单一模型不够用 → 混合模型
没有完美的权限模型,只有适合当前阶段的权限模型。选型的时候想清楚三件事就行:你的系统有多复杂、你的团队有多大精力管权限、你对安全性的要求有多高。系统简单就别搞太复杂,用 RBAC 就够了;系统复杂了也别硬撑,该上 ABAC 就上。核心原则就一句话——够用就好,别过度设计,也别欠设计。


