核心概念:主体、资源、环境、动作、策略——ABAC五要素详解

ABAC 的全称是 Attribute-Based Access Control,基于属性的访问控制。

说白了,就是通过一堆「属性」来判断「谁」能不能对「什么」做「某件事」。这五个要素,我习惯叫它们 ABAC 的「五官」——缺一个,权限判断就做不了。

我记得刚接触 ABAC 时,总把「主体」和「用户」划等号。后来踩了坑才明白,主体远不止是人。咱们一个一个拆开看。

1. 主体(Subject)——谁在发起请求?

主体就是动作的发起方。可以是用户、服务账号、设备,甚至是另一个系统。

你想想看,一个 IoT 场景里,传感器向服务器上报数据,传感器就是主体。一个微服务调用另一个微服务的 API,调用方服务也是主体。

核心要点: 主体 ≠ 用户。主体是「谁在做动作」的那个实体。

主体的属性通常包括:

  • 身份属性: 用户ID、角色、部门、职级
  • 分组属性: 所属项目组、安全等级
  • 上下文属性: 登录IP、设备指纹、会话有效期
我的习惯: 在设计主体模型时,我会把「主体类型」作为一个独立属性。这样策略里可以区分「用户操作」和「服务调用」,避免误放权限。

2. 资源(Resource)——要访问什么东西?

资源就是被访问的对象。文档、数据库记录、API 接口、文件、甚至是一台服务器,都是资源。

我曾在项目中遇到一个需求:同一个文档,不同部门的人只能看到不同字段。这就是资源属性在起作用——文档的「所属部门」属性决定了可见范围。

资源的属性常见的有:

  • 分类属性: 文档类型、数据敏感级别
  • 归属属性: 创建者、所属部门、项目ID
  • 状态属性: 是否已发布、是否归档、是否锁定
我曾经踩过的坑: 把资源属性全部硬编码在策略里。后来资源类型一多,策略变得又臭又长。正确做法是:资源属性应该从资源元数据中动态获取,策略只写匹配规则。

3. 环境(Environment)——在什么条件下?

环境是 ABAC 里最灵活、也最容易被忽略的要素。它描述的是「此时此刻」的上下文。

举个例子:

  • 上班时间(9:00-18:00)允许访问,下班后禁止
  • 从公司内网访问允许,从外网访问需要二次认证
  • 系统处于维护模式时,所有写操作拒绝

环境的属性通常来自系统运行时:

环境属性 示例值 说明
当前时间 2025-03-21 14:30:00 用于时间窗口策略
客户端IP 10.0.1.100 用于网络区域判断
系统运行模式 normal / maintenance 用于全局开关
风险等级 low / medium / high 动态风险评估结果
我个人的建议: 环境属性尽量从基础设施层自动采集,不要依赖前端传入。前端传的时间、IP 都可能被篡改,不安全。

4. 动作(Action)——想做什么?

动作就是主体对资源执行的操作。CRUD 是最基本的,但实际场景远不止这些。

比如:

  • 数据操作: 读取、写入、删除、导出
  • 管理操作: 审批、授权、锁定、解锁
  • 特殊操作: 打印、分享、下载、复制

动作本身也可以有属性。我记得有个金融项目,要求「金额超过 10000 元的转账需要主管审批」。这里的动作属性就是「转账金额」。

关键点: 动作属性让策略更精细。不只是「能不能转账」,而是「能不能转超过 10000 元」。

5. 策略(Policy)——规则是什么?

策略是 ABAC 的大脑。它把主体、资源、环境、动作这四个要素组合起来,输出一个决定:允许还是拒绝。

一个典型的策略结构长这样:

{
  "policyId": "POLICY-001",
  "description": "普通员工只能在工作时间查看自己部门的文档",
  "effect": "deny",  // 或 "allow"
  "conditions": {
    "subject": {
      "role": "employee"
    },
    "resource": {
      "type": "document",
      "department": "{subject.department}"  // 引用主体属性
    },
    "action": {
      "name": "read"
    },
    "environment": {
      "time": "09:00-18:00",
      "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"]
    }
  }
}

这里有个细节:{subject.department} 表示「当前主体的部门属性」。这种引用机制让策略可以复用,不用为每个部门写一条策略。

我曾经犯过的错: 策略里写死了部门名称,结果组织架构调整时改了几十条策略。后来全部改成属性引用,一劳永逸。

五要素的关系图

下面这张图展示了五要素如何协同工作:

ABAC 五要素协同关系图 策略引擎 主体 (Subject) 资源 (Resource) 环境 (Environment) 动作 (Action) 策略 (Policy) 决策结果 (Allow / Deny) 策略引擎综合四要素 + 策略

从图上可以看得很清楚:策略引擎接收主体、资源、环境、动作四个维度的属性,再拿着策略里定义的规则,最终算出「允许」还是「拒绝」。

五要素的实战要点

最后,我总结几个实战中容易忽略的点:

  1. 属性来源要可靠。 主体属性来自认证系统,资源属性来自元数据服务,环境属性来自基础设施。不要信任客户端传过来的任何属性。
  2. 策略要支持属性引用。 像 {subject.department} 这种动态引用,能大幅减少策略数量。
  3. 动作要细分。 别只写 read/write。把「导出」「打印」「分享」都定义成独立动作,策略才能精细控制。
  4. 环境属性要有时效性。 比如「登录时间超过 8 小时需要重新认证」,这个环境属性是动态计算的,不是静态值。
我的经验: 刚开始做 ABAC 时,别追求一步到位。先定义好主体和资源的属性模型,再慢慢加环境和动作。五要素里,属性和策略是核心,其他三个是输入。