4、ABAC属性模型:主体属性、资源属性、环境属性、策略引擎设计思路
好,咱们接着聊。前面讲RBAC的时候,我说过它有个硬伤——权限判断太死板。你想想看,一个“编辑”角色,能不能编辑某篇文章?RBAC只看角色,不看文章是谁的、现在几点、是不是在节假日。这在实际业务里,经常不够用。
所以这一章,我们来聊聊ABAC。说白了,ABAC就是“看人下菜碟”的权限模型。它不依赖角色,而是依赖一堆属性。谁(主体)、对什么(资源)、在什么环境下(环境),这三个维度的属性组合起来,决定你有没有权限。
核心公式: 权限 = 主体属性 + 资源属性 + 环境属性 → 策略引擎判定
4.1 主体属性:你是谁?
主体属性,就是描述“谁在请求”的各种标签。我习惯把它分成两类:
- 身份类:用户ID、部门、职位、职级、所属区域
- 行为类:用户标签(VIP、新用户)、信用等级、认证状态
举个例子。我在做电商SaaS时,有个需求:只有“高级运营”才能查看“销售额超过100万”的店铺数据。这里“高级运营”就是主体属性里的职级。但光有职级还不够,还得看资源属性。
我的经验:主体属性别搞太复杂。我见过有人把用户浏览历史、点击次数都塞进去,结果策略引擎跑起来慢得要命。记住,属性是用来做权限判断的,不是用来做用户画像的。
4.2 资源属性:你要动什么?
资源属性,就是描述“被操作的对象”有什么特征。比如:
- 文档的创建者、所属部门、密级(公开/机密/绝密)
- 订单的金额、状态、所属客户
- API接口的HTTP方法、路径、请求参数
我记得有个项目,客户要求“普通员工只能查看自己创建的合同”。用RBAC你得给每个人建一个角色,太蠢了。用ABAC就一句话:主体.id == 资源.创建者ID。你看,多清爽。
资源属性里,我特别强调一个点:继承属性。比如一个文件夹是“机密”,那它下面的所有文件自动继承这个密级。这样你就不用给每个文件单独打标签了。嗯,这里要注意,继承关系如果太深,性能会下降。我建议最多三层。
4.3 环境属性:什么时候、在哪儿?
环境属性,很多人容易忽略。但它恰恰是ABAC最灵活的地方。环境属性包括:
- 时间:当前时间、是否工作日、是否节假日
- 地点:IP地址、登录设备、网络环境(内网/外网)
- 风险:登录频次、异常行为评分
举个例子。我曾经给一个金融客户做系统,要求“夜间23点到凌晨5点,禁止任何转账操作”。用ABAC写策略就是:环境.当前时间 between 23:00 and 05:00 → 拒绝。简单粗暴。
避坑指南:环境属性千万别用客户端传来的数据做判断。比如“用户说他在内网”,你就信了?我曾经见过一个系统,直接把请求头里的X-Forwarded-For当环境属性,结果被人伪造IP绕过了权限。环境属性必须由服务端自己采集,比如从网关拿到的真实IP、从NTP同步的时间。
4.4 策略引擎设计思路
好,属性有了,谁来算?策略引擎。这是ABAC的大脑。我把它拆成三个核心模块:
| 模块 | 职责 | 我的建议 |
|---|---|---|
| 属性解析器 | 从请求中提取主体、资源、环境属性 | 做成插件化,方便对接不同数据源 |
| 策略匹配器 | 根据属性组合,找到匹配的策略规则 | 用Rete算法优化,别用线性遍历 |
| 决策执行器 | 执行策略,返回允许/拒绝/未决定 | 支持策略优先级和默认拒绝原则 |
策略引擎的代码,我一般这么写(伪代码):
function evaluate(request):
subject = parseSubject(request.user)
resource = parseResource(request.target)
environment = parseEnvironment(request.context)
policies = loadPolicies(subject.dept, resource.type)
for policy in policies:
if match(policy.condition, subject, resource, environment):
return policy.effect // 允许或拒绝
return "deny" // 默认拒绝
这里有个关键点:策略的优先级。我习惯用“拒绝优先”原则。就是说,只要有一条策略明确拒绝,就直接返回拒绝,不再往下匹配。这样可以防止多条策略冲突时出现误判。
核心原则: 没有明确允许,就是拒绝。这是安全系统的铁律。
4.5 实际项目中的ABAC落地
说了这么多,你可能觉得ABAC很完美。其实不然。我在项目中遇到过几个坑:
- 属性爆炸:每个资源都带一堆属性,存储和传输成本飙升。我的解法是:只存关键属性,其他属性通过计算得出(比如“是否热门资源”可以实时算)。
- 策略维护难:业务一多,策略规则成百上千条,没人敢改。我建议用可视化策略编辑器,让运营人员自己配,别让开发改代码。
- 性能瓶颈:每次请求都要跑一遍策略引擎,高并发下扛不住。我的方案是:加一层缓存,把用户-资源-环境的组合结果缓存起来,TTL设个30秒。
最后说一句。ABAC虽然灵活,但别滥用。如果你的系统只有两三个角色,老老实实用RBAC。ABAC适合那种“权限规则三天两头变”的业务。你想想看,是不是这个理?
我的建议:从RBAC起步,等发现角色不够用了,再引入ABAC做补充。别一上来就搞全属性模型,容易把自己绕晕。