2. ABAC 属性模型设计:用户属性、资源属性、环境属性、上下文属性设计原则

属性,是 ABAC 的核心“语言”。

规则之所以能动态计算权限,靠的就是不同维度的属性组合。说白了,没想清楚属性怎么设计,ABAC 就是一锅粥。

我记得刚开始带团队做 ABAC 时,大家把能想到的属性全塞进去,结果策略引擎跑一次要查十几个数据源,性能直接崩了。后来我们总结了一套设计原则,今天跟你聊聊。

核心原则:每个属性应该直接回答一条规则里的“谁、对什么、在什么条件下、做什么”。不回答这四问的属性,基本都是冗余。
ABAC 四维属性模型 权限决策 用户属性 资源属性 环境属性 上下文属性 四种属性共同构成一条策略的完整上下文。缺一种,规则就可能产生漏洞或误判。 设计时先画图,再定义属性字典,最后写规则。

2.1 用户属性设计

用户属性描述“谁”要发起操作。常见的有:部门、职级、角色、区域、入职时间、安全等级等。

设计原则很简单:只采集规则会用到的字段。我在项目里见过有人把用户身高、爱好都存进了属性系统,除了增加数据同步负担,没任何用。

经验之谈:用户属性通常来自 HR 系统或 IAM。优先用 department、jobLevel、region 这种稳定字段。像 lastLoginTime 这种高频变化的字段,除非规则真的需要,否则别放进来——每次属性变更都会触发策略重算,代价很高。

举个例子。某文档系统要求“只有本部门的员工才能编辑本部门文档”。那规则写:

// 伪代码示例
PEP.evaluate({
  user: { department: "Engineering" },
  resource: { ownerDepartment: "Engineering" },
  action: "edit",
  effect: "allow"
});

这里 department 就是关键用户属性。如果你没有这个属性,就得写死部门列表,或者通过角色关联,那就退化到 RBAC 了。

2.2 资源属性设计

资源属性描述“对什么”操作。文件、API、数据库表、微服务端点,都有自己的属性。

我建议把资源属性分成两类:

类别 示例 设计要点
静态属性 资源类型、创建者、所属项目、安全分类 资源创建时写入,很少变化。适合用属性标签存储。
动态属性 当前状态(草稿/已发布)、最后修改时间、使用次数 实时计算或缓存,注意性能。别在每次策略评估时都查数据库。
避坑指南:我曾经在金融项目中,把资源属性里的“客户风险等级”设计成静态标签。结果风控规则需要根据最新交易流水动态计算风险等级,静态属性完全失效。后来改成每日批量更新 + 实时补充计算,才搞定。动态属性一定要和业务更新频率对齐。

资源属性最容易犯的错误是“过度设计”。比如一个文件有 50 个元数据字段,全塞进属性系统。你想想看,策略评估时真的需要检查所有字段吗?通常也就三五个核心字段参与决策。其余字段放业务数据库就好,别往 PIP(策略信息点)里堆。

2.3 环境属性设计

环境属性描述“在什么条件下”。这里的“环境”是独立于用户和资源的外部因素。

常见环境属性:

  • 时间:当前时间、工作日/节假日、上班时间/非上班时间。
  • 网络位置:内网/外网、VPN 接入、IP 段、地理位置。
  • 设备特征:终端类型、操作系统版本、是否越狱。
  • 威胁情报:IP 信誉分、是否属于已知攻击源。

环境属性的特点是“瞬间状态”。每次请求都不一样,而且不能由用户伪造。设计时要保证数据源的实时性和权威性。

我习惯把环境属性封装成独立的 环境上下文服务。PEP 在评估时直接调用这个服务获取当前环境快照,而不是每次都硬编码到规则里。这样环境变化时,只需改服务逻辑,不用改策略规则。

2.4 上下文属性设计

上下文属性是最容易被忽略、也最容易出彩的维度。它描述“这次请求的会话级特征”。

举个例子:用户同时发起两个请求,一个是“查询工资”,一个是“查看同事绩效”。系统需要判断这些请求是否在同一个会话里、是否是越权尝试。

上下文属性通常包括:

  • 会话 ID:用于关联同一用户的多步操作。
  • 请求来源:同一个页面、同一个流程步骤。
  • 操作频率:过去 5 秒内同一用户发出多少次同类请求。
  • 信任等级:多因素认证等级、设备信任分数。
关键区别:上下文属性 不是 用户属性,也不是资源属性。它属于当前请求的“瞬间组合”。用户属性是“你是谁”,上下文属性是“你现在怎么来的、行为表现如何”。

我曾经在电商后台权限项目中,发现有个运营账号总是在凌晨批量导出用户手机号。用户属性(运营角色)和资源属性(用户表)都允许导出,但行为明显异常。后来我们在上下文属性里加入了 requestBatchSize 和 timeWindow,配置一条规则:“单次请求导出超过 100 条且时区在非工作时间,触发审批”。这就是上下文属性的价值——补上了其他三个维度看不到的“动作模式”。

2.5 四类属性的设计对照

维度 回答的问题 数据来源 变更频率 设计侧重
用户属性 谁 HR 系统、IAM、组织架构 低(月/年) 稳定、可枚举
资源属性 对什么 资源元数据、CMDB、业务系统 中(日/周) 精简核心字段
环境属性 在什么条件下 网络设备、时间服务、威胁情报 高(秒/分) 实时、权威
上下文属性 本次请求的特征 会话管理、请求拦截器、行为分析 极高(每次请求) 会话级、细粒度

最后给你个设计清单,每次新增属性时拿这个过一遍:

  1. 这个属性会出现在哪条规则里?
  2. 没有它,规则能否正确决策?
  3. 获取这个属性的成本(延迟、存储、一致性)是否可控?
  4. 属性值是否会频繁变化?变化后是否需要刷新缓存?
一条实操建议:先把规则写出来,再反推需要哪些属性。不要先建属性库再写规则——那样你会收集一堆用不上的垃圾属性。我每次都跟团队说:先画规则草图,再建属性字典,最后落地实现。顺序反了,必返工。