ABAC 进阶:基于属性的访问控制策略
前面聊了 RBAC 的「角色即权限」模型,挺实用的。但我觉得在真实生产环境里,很多场景 RBAC 扛不住。比如数据脱敏策略:「销售部的人只能看所属大区的客户手机号后四位,只有总监才能看完整号码」。用角色硬编码?想想就头疼。
这时候 ABAC 就派上用场了。说白了,ABAC 不是看「你是谁」,而是看「你 + 资源 + 环境」组合起来满足什么条件。每次访问都动态评估,灵活得多。我在为一家金融科技公司设计权限方案时,就用 ABAC 解决了多维度动态脱敏的难题。
ABAC 的四个核心属性
记住四类属性,缺一不可:
- 主体属性(Subject):用户 ID、部门、职级、区域、安全标签。我记得有一次,客户要求「非 IT 部门不得访问云数据库的 root 密码」——这就是主体属性过滤。
- 资源属性(Resource):数据库名、表名、行级标签、敏感度等级。比如某张表打了「PII」标签,只有通过属性匹配才能查到。
- 环境属性(Environment):访问时间、IP 段、网络类型、客户端版本。我习惯在内网场景加一条「工作时间 9:00-18:00 允许批量查询,其余时段只允许单行查询」。
- 动作属性(Action):SELECT、INSERT、UPDATE、DELETE、EXPORT。有些动作天生高危,比如 DROP TABLE。
核心思想:将访问控制决策从「角色」中解耦,变成「属性 + 规则」的布尔组合。每次请求都实时算一次,灵活但必须控好性能。
规则引擎架构:PDP / PEP / PRP
你想想看,ABAC 落地需要三个核心组件,缺一个都跑不转:
| 组件 | 全称 | 职责 |
|---|---|---|
| PEP | Policy Enforcement Point | 拦截请求,向 PDP 发起决策咨询,并执行决策(允许/拒绝) |
| PDP | Policy Decision Point | 接收属性上下文,评估规则,返回 Permit/Deny/NotApplicable |
| PRP | Policy Retrieval Point | 存储规则定义(策略库),供 PDP 拉取 |
我曾经在项目里见过团队把规则写死在代码里,每次变更都要发版。后来改成了中心化的 PRP + 热加载 PDP,规则改完秒级生效。这是 ABAC 的真正优势。
规则表达:从自然语言到策略语言
写规则最怕模糊。我习惯用类似 XACML 的简化 DSL 来描述,比如:
// 规则:只有本人的数据,且在工作时间,才允许查看手机号
rule "ViewOwnPhone"
when
subject.department == resource.owner_department
and subject.user_id == resource.owner_id
and environment.time.hour between 9 and 18
then
permit
注意这里没有「角色」,全是属性比较。实际生产里,属性会从统一身份系统、数据资产目录、环境变量里实时拉取。
我的建议:规则引擎避免用自然语言字符串解析,尽量用结构化的策略对象(比如 protobuf/JSON schema),便于版本管理和自动化测试。
动态评估的性能陷阱
ABAC 最让人担心的就是性能。每次请求都要查 N 个属性、跑一遍规则树。嗯,这里要注意:
- 属性缓存:主体属性和环境属性变更频率低,缓存 TTL 设长一点。我在项目中把主体属性缓存到 5 分钟,资源属性的敏感标签缓存到 1 分钟,PDP 吞吐量提升了 4 倍。
- 规则预编译:别在热路径上解析策略文本。把 DSL 编译成 AST 或布尔表达式树,评估时只走内存。
- 短路评估:一旦匹配到 Deny 规则,直接返回,不再继续算 Permit 分支。
避坑指南:我曾经因为全局缓存了用户部门属性,忘了考虑用户调岗后缓存未失效,导致离职员工还能看到旧部门的敏感数据。后来加了缓存变更监听 + 强制刷新接口,才算解决。
实际流程:一次动态权限评估的完整路径
用一张图来帮大家理解整个调用链:
实战案例:基于属性的行级数据脱敏
拿数据脱敏说事最直观。假设用户表有手机号列,访问控制要求:
- 同一部门员工只能看到所属团队人员的手机号,且中间四位打星号。
- 部门经理可看完整手机号,但只限本部门。
- HR 部门的 HRBP 可跨部门查看员工手机号,但需要标记为「敏感操作」记日志。
用 RBAC 做?你得把「查看完整手机号」这个动作拆分进 N 个角色。ABAC 就简单了:
rule "MaskPhone"
when
subject.role == "employee"
and subject.department == resource.department
then
mask(resource.phone, 4, 8) // 4-7位打星
permit
rule "FullPhoneForManager"
when
subject.role == "manager"
and subject.department == resource.department
then
permit // 返回完整手机号
rule "HRBPCrossDept"
when
subject.department == "HR"
and subject.sub_role == "hrbp"
then
audit_log("HRBP cross-dept view", subject.user_id, resource.id)
permit
你看,属性组合解决了,而且新增规则完全不影响已有权限。
核心收获:ABAC 不是银弹,但当你面对多维度、细粒度、频繁变化的访问控制需求时,它是唯一能优雅收敛的方案。配合规则引擎热更新,运维级效率提升非常明显。
小结
ABAC 进阶的核心就是「用属性说话」和「动态评估」。我从 2018 年开始在生产环境大规模推广 ABAC,踩过规则膨胀的坑,也吃过属性传递丢失的亏。但只要把握好四个属性维度,设计好 PDP/PEP/PRP 组件,配上合理的缓存和预热策略,它比 RBAC 更经得起业务翻来覆去的折腾。