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 核心架构,你看一眼就能明白整体流程。

ABAC 核心架构图 ABAC 核心架构 主体属性 资源属性 环境属性 动作 规则引擎 决策结果(允许/拒绝) 说明 属性由策略信息点(PIP) 提供,规则由策略决策点 (PDP)执行。

流程很简单:

  1. 用户发起请求,携带主体属性(你是谁)
  2. 系统获取资源属性(你要操作什么)和环境属性(当前上下文)
  3. 三者连同动作一起送入规则引擎
  4. 规则引擎匹配预定义的策略,输出允许或拒绝

这里有个关键角色——策略信息点(PIP)。它负责收集和提供属性数据。比如用户信息从用户服务拿,文档信息从文档服务拿,时间信息从系统时钟拿。PIP 的设计好坏直接影响 ABAC 的性能和可维护性。

我的经验:PIP 最好做成插件化。我在一个项目中把 PIP 设计成 SPI 接口,每个属性源实现一个 Provider。这样新增属性源时,只需要加一个 Provider 实现,不用改核心代码。后面讲架构时会详细展开。

1.5 什么时候该用 ABAC?

最后给个实用建议。判断是否该用 ABAC,问自己三个问题:

  • 权限规则是否经常变化? 是 → ABAC 更合适
  • 是否需要结合时间、地点、设备等环境因素? 是 → ABAC 是刚需
  • 角色数量是否已经超过 50 个且还在增长? 是 → 考虑 ABAC 来瘦身

如果三个问题都是「是」,那别犹豫了,ABAC 就是你要的答案。如果只有一两个「是」,可以考虑 RBAC + ABAC 混合模式。后面章节我会专门讲混合架构怎么设计。