1. ABAC 概述:从“你是谁”到“你处在什么环境”

咱们直接开门见山。ABAC,全称 Attribute-Based Access Control,翻译过来就是“基于属性的访问控制”。

很多朋友第一次听到这个名词,第一反应是:“这不就是 RBAC 的升级版吗?”
嗯,对,但不全对。我个人的理解是:ABAC 不是要取代 RBAC,而是解决 RBAC 搞不定的事。

先看一个我早年踩过的坑。当时给一个金融系统做权限设计,用的是 RBAC。角色分得挺细:出纳、会计、主管、风控……结果业务方提了个需求:
“同一个会计,在工作时间能看客户资料,下班后不能看;在办公室能导出报表,在咖啡厅不能导出。”
我当时就懵了。RBAC 里角色是静态的,它哪管你在哪、什么时间?
这就是 ABAC 要解决的问题——把“你是谁”和“你处在什么环境”结合起来做决策。

一句话总结:ABAC 是一种基于主体、资源、环境、操作四类属性的动态授权模型。它不依赖固定的角色,而是通过属性规则实时计算权限。

ABAC 与 RBAC 的核心区别

我习惯用一个表格来对比,这样最直观:

对比维度 RBAC(基于角色) ABAC(基于属性)
授权依据 角色(静态分组) 属性规则(动态计算)
粒度 粗粒度(角色级) 细粒度(属性级)
灵活性 低,角色变更需重新分配 高,规则变更即时生效
上下文感知 不支持 支持(时间、地点、设备等)
规则复杂度 简单,适合稳定场景 中等偏高,适合动态场景
典型场景 企业内部 OA、ERP 云平台、微服务、IoT、金融风控

你看,RBAC 像是一张“员工工牌”,戴上了就是某个角色,走到哪都一样。
ABAC 更像是一套“智能门禁系统”,它不光看你是谁,还看你现在几点、在哪个门、手里有没有危险品。

我的建议:如果你的系统角色不超过 20 个,且权限规则很少变化,用 RBAC 就够了。别为了炫技上 ABAC,那是给自己找麻烦。

ABAC 的核心优势

为什么这几年 ABAC 越来越火?说白了,就三个字:灵活、精细、动态。

  • 灵活:规则可以随时调整,不用重新分配角色。我曾经帮一个电商平台改过规则——从“运营能看所有订单”改成“运营只能看自己负责的品类订单”,改一条策略就搞定,不用动任何人的角色。
  • 精细:可以控制到“某个人在某个时间对某个资源的某个字段是否有权限”。比如:医生在工作时间能查看患者病历,但不能导出;下班后连查看都不行。
  • 动态:权限决策是实时的。每次请求都重新计算,所以能感知上下文变化。比如:用户从内网切换到外网,权限自动降级。

注意:ABAC 的灵活是有代价的。规则多了以后,性能会下降,而且策略管理会变得复杂。我曾经见过一个项目,ABAC 规则写了 3000 多条,最后连运维都搞不清哪条生效了。所以,规则数量一定要控制,能用 RBAC 兜底的场景就别硬上 ABAC。

ABAC 的典型应用场景

我挑几个自己实际接触过的场景,给你讲讲:

  1. 云平台多租户权限
    同一个云账号,在不同项目空间里权限不同。比如:用户 A 在“项目 X”是管理员,在“项目 Y”只是只读成员。ABAC 通过“项目 ID”属性来区分,非常自然。
  2. 医疗系统数据隔离
    医生只能看自己科室的患者病历,且只能在工作时间访问。ABAC 规则可以写成:subject.department == resource.department && time.between(8:00, 18:00)。
  3. 金融风控中的操作限制
    大额转账需要双人复核,且必须在公司内网操作。ABAC 可以结合“金额 > 10000”、“操作人 != 复核人”、“network == internal”三个属性做决策。
  4. 微服务 API 网关鉴权
    每个微服务有自己的属性标签,调用方也有自己的属性。网关根据双方属性匹配规则,决定是否放行。这比硬编码 灵活得多。

ABAC 核心逻辑框架图

下面这张图,是我自己画的一个 ABAC 决策流程。你看一眼就能明白它的工作方式:

ABAC 核心决策流程 ABAC 核心决策流程 主体属性 用户ID / 部门 / 角色 资源属性 类型 / 分类 / 敏感级别 环境属性 时间 / 地点 / 网络 操作属性 读 / 写 / 导出 策略决策引擎 匹配属性规则 → 计算授权结果 授权结果:允许 / 拒绝 说明 ABAC 每次请求都重新计算四类属性, 不依赖预分配的角色,实现真正的动态授权。

一个简单的 ABAC 规则示例

光说理论太干,我给你写一段伪代码,模拟 ABAC 策略引擎的决策逻辑:

// 策略:医生只能在工作时间查看自己科室的患者病历
function evaluateAccess(subject, resource, environment, operation) {
    // 1. 检查操作类型
    if (operation != "read") return "deny";
    
    // 2. 检查科室匹配
    if (subject.department != resource.department) return "deny";
    
    // 3. 检查时间范围
    if (environment.time < "08:00" || environment.time > "18:00") return "deny";
    
    // 4. 检查工作日
    if (environment.day == "Saturday" || environment.day == "Sunday") return "deny";
    
    return "allow";
}

你看,这个规则里没有出现任何具体的用户名或角色名。全是属性匹配。
这就是 ABAC 的精髓——规则与用户解耦,权限与上下文绑定。

一个小技巧:刚开始设计 ABAC 策略时,别想着一步到位。先列出所有可能影响权限的属性维度,然后从最关键的 3-5 个开始写规则。规则越少,越容易调试。

好了,这一章就聊到这。ABAC 的核心概念其实不复杂,难的是后面怎么设计属性模型、怎么写策略、怎么优化性能。这些我们后面慢慢展开。