4. AI应用授权模型设计

AI应用与传统Web系统最大的差别,在于它的权限请求不是一次性的“打开页面”,而是由模型推理动态触发的:一次对话可能先调用模型、再检索知识库、再执行一个外部工具,最后把结果写回会话。授权模型如果只覆盖“用户能不能访问某个接口”,就会在模型调用、数据访问、工具执行三个环节留下大量盲区。本节围绕RBAC、ABAC、ReBAC三种模型,讨论它们分别适合承载哪类授权判断,以及如何在同一套AI应用里组合落地。

三种模型的判断依据不同

RBAC(基于角色的访问控制)把权限绑定到角色,用户通过角色获得权限。它的判断输入是“主体—角色—权限”,适合稳定、边界清晰的粗粒度控制,例如“客服角色可以调用对话模型”“数据分析师角色可以访问报表工具”。RBAC的优点是易管理、易审计,缺点是难以表达“同一角色在不同数据范围、不同时间、不同工具参数下权限不同”的细粒度需求。

ABAC(基于属性的访问控制)把权限判断交给属性与策略:主体属性(部门、职级、认证强度)、资源属性(数据分级、所属租户)、环境属性(时间、IP、设备可信度)、动作属性(读、写、调用、导出)共同参与决策。它适合表达“财务部员工在工作时间、通过企业设备,可以读取本部门非敏感数据”这类条件组合。ABAC的代价是策略数量增长快,属性来源必须可信。

ReBAC(基于关系的访问控制)把权限判断建立在实体之间的关系图上,典型形式是“用户A是文档D的编辑者”“团队T是项目P的成员”“工具X被授权给代理Y”。它天然适合协作型、层级型、共享型的资源授权,例如“只有被邀请到该会话的成员,才能读取该会话上传的附件”。ReBAC擅长回答“谁和谁有关系”,但对环境条件、数值阈值的表达能力弱于ABAC。

AI应用授权:三类模型在三个执行环节的落点 请求主体 用户 / 会话 user_id, tenant_id AI代理 / 服务账号 agent_id, scope 属性上下文 部门/时间/设备 关系上下文 成员/所有者/共享 PEP 策略执行点 拦截并组装请求 调用PDP决策 AI应用执行链 ① 模型调用 判断:能否调用该模型/版本/区域 约束:token上限、并发、敏感等级 主用模型:RBAC + ABAC ② 数据访问 判断:能否读取该文档/表/向量库分片 约束:行级过滤、字段脱敏、租户隔离 主用模型:ReBAC + ABAC ③ 工具执行 判断:能否调用该工具及具体参数 约束:写操作二次确认、金额/范围阈值 主用模型:ABAC + ReBAC PDP 策略决策点:合并三类判断 拒绝优先 · 最小权限 · 全程留痕 策略与治理 RBAC 角色表 role → permission 粗粒度、稳定 ABAC 策略集 subject/resource/env 条件组合、动态 ReBAC 关系图 user→team→project 共享、继承、层级 审计与回溯 决策日志:谁/何时/为何 命中策略ID、拒绝原因 异常调用告警

模型调用场景:RBAC定边界,ABAC控参数

模型调用是AI应用的第一道授权关口。这里最需要回答两个问题:这个主体能不能调用这个模型,以及调用时允许携带什么参数。前者适合RBAC:把“可调用模型清单”作为权限授予角色,例如角色support_agent拥有model:chat-basic:invoke,角色risk_analyst拥有model:chat-pro:invoke与model:embedding:invoke。后者适合ABAC:即使角色允许调用,也要检查请求中的max_tokens、temperature、data_classification是否超出策略允许范围。

一个可落地的判断顺序是:先做RBAC粗筛,命中角色权限后再进入ABAC细判。例如策略要求“data_classification=internal的请求只能路由到境内模型端点,且max_tokens ≤ 4096”。当请求携带data_classification=confidential时,即使角色拥有调用权限,ABAC也会拒绝或降级到本地小模型。这样既保留了角色管理的简洁性,又避免了“有角色就什么都能调”的过度授权。

数据访问场景:ReBAC管“看得见”,ABAC管“看多少”

数据访问是AI应用最容易出问题的环节,因为检索增强生成会把多个数据源的结果拼进同一个上下文。ReBAC在这里非常关键:用户能读哪些文档,往往取决于他与文档、团队、项目、会话之间的关系。例如关系图中有user:u1001 → member → team:t20、team:t20 → viewer → folder:f7、folder:f7 → contains → doc:d88,那么u1001对d88就拥有继承而来的读权限。当用户把文档分享给会话时,可以建立session:s5 → shared_with → user:u1002,让被邀请者获得该会话上下文的读取权,而不必复制一份数据。

但ReBAC只回答“有没有关系”,不回答“能看多少”。同一份文档里可能包含手机号、金额、身份证号,这时需要ABAC做字段级和行级控制:策略可以规定“role=analyst且department=finance时,可读取amount字段;其他角色读取时该字段返回掩码”。在向量检索场景中,ABAC还可以约束“只召回tenant_id与请求方一致的分片”,防止跨租户语义泄漏。ReBAC与ABAC的组合,正好覆盖“关系可达”与“属性合规”两个维度。

工具执行场景:ABAC管风险,ReBAC管委托

工具执行是权限风险最高的环节,因为工具往往带有副作用:发邮件、改工单、转账、删除记录。这里RBAC只能回答“这个角色能不能用这个工具”,无法回答“这次调用是否安全”。ABAC需要介入参数级判断,例如“tool:refund单笔金额不得超过5000元,超过必须由role=supervisor二次审批”“tool:send_email的收件人域名必须在白名单内”。这些条件依赖请求参数、环境属性和主体属性,是典型的ABAC策略。

ReBAC则解决代理与委托问题。AI代理经常代表用户执行操作,此时需要判断“代理是否有权代表该用户调用该工具”。可以在关系图中建立agent:a3 → delegated_by → user:u1001,并限定委托范围scope=tool:refund,limit=5000。当代理尝试调用超出委托范围的工具时,ReBAC直接拒绝。这样,工具执行的授权链就是“用户→代理→工具→参数”四层校验,而不是简单的角色放行。

组合落地:统一PDP与拒绝优先

三种模型不应各自为政,而应汇聚到一个策略决策点(PDP)。请求进入时,PEP先收集主体属性、资源关系、环境上下文和动作参数,再按“RBAC粗筛→ReBAC关系判定→ABAC条件判定”的顺序求值,任一环节拒绝则整体拒绝。这种“拒绝优先”的顺序能避免细粒度策略被粗粒度角色绕过。

下面是一段策略伪代码,展示三类判断如何合并。示例参数为教学假设,实际部署需替换为真实属性源与策略引擎。

def authorize(req):
    # 1) RBAC:角色是否拥有动作权限
    if not rbac.has_permission(req.subject.roles, req.action):
        return Deny("RBAC_NO_PERMISSION")

    # 2) ReBAC:主体与资源是否存在可达关系
    if req.resource.type == "document":
        if not rebac.check(req.subject.id, "viewer", req.resource.id):
            return Deny("REBAC_NO_RELATION")

    # 3) ABAC:属性与参数是否满足策略
    if req.action == "tool:refund":
        if req.params.amount > 5000 and "supervisor" not in req.subject.roles:
            return Deny("ABAC_AMOUNT_EXCEEDED")
    if req.env.data_classification == "confidential" and req.env.region != "cn":
        return Deny("ABAC_REGION_VIOLATION")

    return Allow("POLICY_MATCHED")
落地建议:RBAC角色数量控制在几十个以内,避免角色爆炸;ABAC策略按“资源类型+动作”分组管理,每条策略必须有唯一ID和责任人;ReBAC关系图要设置关系过期时间,尤其是会话共享和临时委托,防止权限长期残留。
常见误区:只用RBAC覆盖全部场景,会导致“客服角色能读所有客户数据”;只用ABAC而缺少关系模型,会导致共享文档、团队继承等场景难以表达;只用ReBAC而忽略环境与参数,会让工具执行失去风险控制。三者是互补关系,不是替代关系。

判断授权设计是否合格,可以观察三个信号:第一,新增一个数据源或工具时,是否需要改动大量角色定义;第二,能否在不复制数据的前提下完成跨团队共享;第三,审计日志能否还原“为什么这次调用被允许或拒绝”。如果三个问题都有清晰答案,说明RBAC、ABAC、ReBAC已经在模型调用、数据访问、工具执行三个场景中形成了可维护的组合,而不是堆叠在一起的孤立规则。