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很完美。其实不然。我在项目中遇到过几个坑:

  1. 属性爆炸:每个资源都带一堆属性,存储和传输成本飙升。我的解法是:只存关键属性,其他属性通过计算得出(比如“是否热门资源”可以实时算)。
  2. 策略维护难:业务一多,策略规则成百上千条,没人敢改。我建议用可视化策略编辑器,让运营人员自己配,别让开发改代码。
  3. 性能瓶颈:每次请求都要跑一遍策略引擎,高并发下扛不住。我的方案是:加一层缓存,把用户-资源-环境的组合结果缓存起来,TTL设个30秒。

最后说一句。ABAC虽然灵活,但别滥用。如果你的系统只有两三个角色,老老实实用RBAC。ABAC适合那种“权限规则三天两头变”的业务。你想想看,是不是这个理?

我的建议:从RBAC起步,等发现角色不够用了,再引入ABAC做补充。别一上来就搞全属性模型,容易把自己绕晕。