让身份过滤、文档版本和引用校验贯穿检索链路,避免越权内容进入模型上下文。
本文于 2026-09-12 补充整理,按 2026-04 专题归档。示例为方案设计,参数用于说明方法,不代表已上线项目或实测成果。
权限控制必须早于模型读取
企业知识库里,最严重的错误不一定是答错,而是把另一个项目的内部信息答对。让模型遵守“不要泄露”不足以构成权限隔离;未授权内容应尽可能在检索层被排除,并在返回前再次校验。
示例中的主体由认证会话确定,包含租户、用户和组织关系。检索条件由服务端构造。模型提供查询词,不能自行覆盖 tenant_id 或增加可访问项目。
给证据建立明确结构
{
"evidenceId": "ev-42",
"documentId": "deploy-guide",
"documentVersion": "v7",
"chunkId": "c12",
"locator": "第 3 节 / 凭据轮换",
"aclVersion": "a9",
"retrievedAt": "2026-09-12T10:00:00+08:00"
}
这只是合成示例。文档引用应由后端依据证据 ID 解析,模型无需生成任意 URL。输出中引用了不属于本次证据集合的 ID,直接判为无效,不应尝试“智能修正”到名称相似的文档。
引用有效性至少包含两个问题:来源是否真实且可访问,来源是否支持对应结论。第一项可程序化检查,第二项往往还需要对陈述和证据进行评判。
数据库隔离是第二道约束
应用查询必须携带租户与权限过滤,同时可以使用数据库行级安全作为防御层。PostgreSQL 行级安全文档提醒,表所有者和具有特定权限的角色可能绕过策略,因此应用账号和策略测试同样重要。
使用连接池设置会话上下文时,要确认事务结束后不会把前一位用户的身份遗留给下一位用户。更安全的设计通常是事务范围的身份设置,并在每次查询路径验证上下文存在。缺少身份时应拒绝查询,而不是退回全库检索。
文档还有部门、项目、密级等属性时,仅有 tenant 过滤不够。权限决策必须由权威服务或可验证的策略快照给出。
从检索到回答存在时间差
用户在 10:00 检索到文档,管理员在 10:01 撤销权限,模型在 10:02 才生成答案。这个窗口不能通过入库时的 ACL 一次性解决。
对敏感场景,回答发送前重新检查证据权限;引用链接打开时再次鉴权。若权限已撤销,不能只删除引用标记却保留基于该证据生成的敏感结论,应丢弃或重新生成受影响回答。
如果系统采用流式输出,严格撤权语义更难实现:已经发出的内容无法收回。敏感答案可以先缓冲验证再发送,或者只流式发送进度事件,把最终答案延后。
缓存同样属于权限链路
缓存键不能只有问题文本。需要包含租户、权限指纹、知识版本和策略版本,或采用其他能够证明隔离正确的分区方式。相同问题在不同权限下本来就可能有不同答案。
缓存命中时仍应验证过期与撤销状态。权限变化频繁时,单纯延长 TTL 虽能减少检索,也会扩大旧权限继续生效的窗口。
如何验收这条链路
准备名称相同、内容不同的 A/B 租户文档,分别用两个用户提问;随后对 A 用户撤销一份文档权限,再重复提问并打开旧引用。检查检索结果、重排输入、模型上下文、缓存响应和链接访问五个位置。
正确结果不仅是界面看不到 B 的文档标题,还包括 B 的内容没有进入模型或第三方重排器。架构评审时,这条数据路径比一句“支持 RBAC”更有说服力。
