1. ABAC 初探:什么是 ABAC?为什么需要 ABAC?ABAC 与 RBAC 的对比
说实话,做了这么多年权限系统,我见过太多团队在权限设计上栽跟头。有的项目上线半年,权限代码改了几十次,最后还是被业务方吐槽「管不住」。问题出在哪?说白了,就是选错了模型。
今天咱们先聊聊 ABAC——基于属性的访问控制。别急着看代码,先把概念吃透。
1.1 什么是 ABAC?
ABAC,全称 Attribute-Based Access Control,翻译过来就是「基于属性的访问控制」。它的核心思想很简单:能不能访问某个资源,取决于一组属性条件是否满足。
举个例子。你有个文档系统,要求「只有部门经理才能查看本部门的财务报表」。用 ABAC 来描述就是:
- 主体属性:用户角色 = 部门经理
- 资源属性:文档类型 = 财务报表,所属部门 = 用户所在部门
- 环境属性:当前时间在工作时间内(可选)
- 动作:查看
当这些条件全部匹配,权限就放行。少一个都不行。
核心公式:
权限判定 = 主体属性 ∩ 资源属性 ∩ 环境属性 ∩ 动作 → 允许/拒绝
我个人习惯把 ABAC 理解成「规则引擎 + 属性字典」。你定义好规则,引擎根据传入的属性自动计算结果。不需要硬编码,不需要写 if-else 地狱。
1.2 为什么需要 ABAC?
你可能会问:RBAC(基于角色的访问控制)不是挺好的吗?为什么还要搞 ABAC?
嗯,这里有个关键点。RBAC 在简单场景下确实够用,但一旦业务复杂起来,它的短板就暴露了。
我在项目中遇到过这样一个需求:一个跨国企业的审批系统,要求「中国区的财务总监可以审批金额在 100 万以下的报销单,但如果是美国区的报销单,金额上限是 50 万」。用 RBAC 怎么搞?你得建两个角色:「中国区财务总监」和「美国区财务总监」。如果再加个欧洲区呢?再加个东南亚区呢?角色数量会爆炸。
ABAC 的解法就优雅多了:
规则:允许审批报销单
条件:
- 用户.角色 == "财务总监"
- 用户.区域 == 报销单.区域
- 报销单.金额 <= 用户.区域.审批上限
一条规则,覆盖所有区域。这就是 ABAC 的价值——灵活、可扩展、维护成本低。
总结一下,ABAC 的核心优势:
- 细粒度控制:可以精确到单个资源、单个属性
- 动态适应:属性变化时,权限自动调整,无需改代码
- 减少角色膨胀:用属性组合替代大量角色定义
- 上下文感知:能结合时间、地点、设备等环境因素
避坑指南:我曾经在一个项目中过度使用 ABAC,把简单的「管理员 vs 普通用户」也写成属性规则。结果规则数量膨胀到 200 多条,排查问题非常痛苦。记住:简单场景用 RBAC,复杂场景用 ABAC,两者可以共存。
1.3 ABAC 与 RBAC 的对比
咱们直接上表格,看得更清楚。
| 对比维度 | RBAC | ABAC |
|---|---|---|
| 核心概念 | 角色(Role) | 属性(Attribute) |
| 粒度 | 粗粒度(角色级别) | 细粒度(属性级别) |
| 灵活性 | 低,角色变更需重新分配 | 高,属性变更自动生效 |
| 维护成本 | 角色数量少时低,多时高 | 规则设计好之后较低 |
| 适用场景 | 组织架构稳定、权限变化少 | 多维度、动态变化的权限需求 |
| 学习曲线 | 低,容易理解 | 中等,需要理解属性模型 |
| 性能 | 高,直接查角色-权限映射 | 中等,需要实时计算规则 |
说白了,RBAC 是「你是什么人,就能做什么事」。ABAC 是「你是什么人 + 在什么环境 + 对什么东西 + 做什么事,综合判断」。
你想想看,如果业务场景里只有「管理员」「编辑」「访客」这三种角色,RBAC 完全够用。但如果出现「只有工作日上午 9 点到 11 点,且 IP 在公司内网,且文档状态为草稿时,才允许编辑」这种需求,RBAC 就抓瞎了。这时候 ABAC 就是正解。
注意:不要为了用 ABAC 而用 ABAC。我见过有人把「性别」「年龄」这种静态属性也写进规则,结果规则变得又臭又长。ABAC 适合的是动态、多维度、跨角色的权限场景。静态权限用 RBAC 就够了。
1.4 ABAC 的核心架构
下面这张图是我自己总结的 ABAC 核心架构,你看一眼就能明白整体流程。
流程很简单:
- 用户发起请求,携带主体属性(你是谁)
- 系统获取资源属性(你要操作什么)和环境属性(当前上下文)
- 三者连同动作一起送入规则引擎
- 规则引擎匹配预定义的策略,输出允许或拒绝
这里有个关键角色——策略信息点(PIP)。它负责收集和提供属性数据。比如用户信息从用户服务拿,文档信息从文档服务拿,时间信息从系统时钟拿。PIP 的设计好坏直接影响 ABAC 的性能和可维护性。
我的经验:PIP 最好做成插件化。我在一个项目中把 PIP 设计成 SPI 接口,每个属性源实现一个 Provider。这样新增属性源时,只需要加一个 Provider 实现,不用改核心代码。后面讲架构时会详细展开。
1.5 什么时候该用 ABAC?
最后给个实用建议。判断是否该用 ABAC,问自己三个问题:
- 权限规则是否经常变化? 是 → ABAC 更合适
- 是否需要结合时间、地点、设备等环境因素? 是 → ABAC 是刚需
- 角色数量是否已经超过 50 个且还在增长? 是 → 考虑 ABAC 来瘦身
如果三个问题都是「是」,那别犹豫了,ABAC 就是你要的答案。如果只有一两个「是」,可以考虑 RBAC + ABAC 混合模式。后面章节我会专门讲混合架构怎么设计。