Dify 1.17.x 给知识库带来两件值得立刻动手的事:其一是数据集级 API Key——过去知识库的服务 API 密钥是工作区级的,一把钥匙能读写整个租户下所有知识库,给集成方授权「只读一个库」在密钥层面根本做不到;现在可以在创建时把 Key 绑定到具体知识库,越权访问直接 403。其二是 1.17.1 修复了一批「内容在无报错情况下被错误提取」的知识库 Bug——CSV 前导零变浮点、Notion 表格列错位等,修复只对新导入生效,已索引的错误文本不会自动纠正。本篇把「收紧密钥」和「排查重导」两条线一次讲完。
先理解:密钥作用域的风险模型
| 作用域 | 能做什么 | 风险面 |
|---|---|---|
| 工作区级 Key(旧行为,仍在) | 读写该工作区全部知识库,含「列出全部」这类不带数据集 ID 的端点 | 泄露即全库暴露;给一个集成授权等于给所有库授权 |
| 知识库级 Key(新能力) | 仅限绑定的那个知识库的文档与检索端点 | 访问其他数据集返回 403;「列出全部」类端点同样拒绝 |
注意一条兼容性设计:升级后已有的存量 Key 保持未绑定状态、行为不变(还是工作区级)。也就是说升级本身不会破坏现有集成,但也不会自动帮你收紧——收窄授权是一个需要主动执行的运维动作,这正是本篇 Step 4 的内容。
升级红线先确认。如果你的部署用的是 Dify 内置 Weaviate,从旧版本升上来需要分阶段手动升级向量库,直接拉镜像重启可能静默且永久性破坏向量检索——升级操作见站内《Dify 1.17.1 自托管升级避坑》专篇。本篇默认你已在受支持版本上。
Step 1:核对版本,盘点现有密钥与知识库
# 确认版本(自托管)
curl -s http://localhost/console/api/version
# 盘点清单(在控制台界面逐项登记到表格):
# 1. 本工作区有多少个知识库,各自 sensitivity(公开/内部/敏感)
# 2. 现存多少个知识库服务 API Key,各自被哪些集成在用
# 3. 每个集成实际只需要访问哪几个库
盘点产出一张「集成 → 实际所需知识库」映射表。这张表决定了后续每个按库 Key 该绑到哪、哪些存量 Key 可以直接作废。映射不清就先别发新 Key——按库授权的价值全在「绑对了库」,绑错库反而制造新的排查负担。
Step 2:创建绑定单个知识库的 API Key
操作路径(1.17.x 控制台):
进入目标知识库 → API 访问(API Access)面板
→ 创建 API Key
→ 作用域选择器:工作区 / 此知识库
→ 选「此知识库」→ 保存
命名规范建议(方便半年后对账):
kb-financial-reports -- for-rag-service
(哪个库 + 给谁用,两段式命名)
创建完成后立刻把 Key 交给对应集成方替换配置,并在你的密钥台账里登记:Key 前几位(用于辨认)、绑定的库、用途、负责人。密钥值只出现这一次,马上收好。
Step 3:验证 403 边界
# 1) 访问绑定的库 —— 预期 200
curl -s -o /dev/null -w "%{http_code}\n" \
-H "Authorization: Bearer kb-绑定的KEY" \
"http://localhost/v1/datasets/被绑定库ID/documents"
# 2) 访问另一个库 —— 预期 403
curl -s -o /dev/null -w "%{http_code}\n" \
-H "Authorization: Bearer kb-绑定的KEY" \
"http://localhost/v1/datasets/其他库ID/documents"
# 3) 不带数据集 ID 的「列出全部」端点 —— 预期 403
curl -s -o /dev/null -w "%{http_code}\n" \
-H "Authorization: Bearer kb-绑定的KEY" \
"http://localhost/v1/datasets"
预期效果:请求一返回 200,请求二、三返回 403。三个码都对,说明按库授权生效、越权边界成立。把这三条 curl 存成回归脚本——以后升级版本、变更配置后重跑一遍,密钥边界有没有被改动一测便知。
集成方代码要同步适配 403。过去一把全库 Key 的集成代码里,可能存在「先列全部再过滤」的写法——换成按库 Key 后这类调用会直接 403。改造时提醒集成方改用具体数据集 ID 的端点,并给 403 加上清晰的报错信息,别让它以神秘失败的形式出现在生产上。
Step 4:存量 Key 轮换
存量 Key 保持工作区级全库行为,等于风险面原封不动。轮换顺序按「风险 × 难度」排:先换对外暴露的(第三方集成、边缘服务),再换内部长期没人认领的(盘点时找不到负责人的 Key 直接作废,观察有没有人报障),最后换核心内部服务(挑发布窗口替换)。每换一把:创建按库新 Key → 集成方替换 → 回归三请求验证 → 作废旧 Key → 更新台账。
轮换窗口期新旧 Key 并存是常态,但要有截止日。「先加新、后删旧」是安全做法,但旧 Key 拖着不删,收紧就永远停在纸面上。给每把旧 Key 标注作废期限,到期即删。
Step 5:提取 Bug 自查——你的索引里有多少错文本
1.17.1 修复的这批 Bug 有个共同特点:提取过程不报错,坏文本悄悄进了索引。升级只是堵住了新入口,已索引的错误内容要靠你自己排查:
| 文档类型 | Bug 表现(修复前导入的会中招) | 自查方法 |
|---|---|---|
| CSV | 前导零被当成数字(00123 → 123.0);空单元格变成字符串 nan;含 NA/NULL 的单元格被当缺失值丢掉 | 检索原文件里的编号类字段(单号、编码),比对索引文本是否变形 |
| Notion 表格 | 单元格内多段富文本被拆成多余列,整表错位;空单元格导致整行左移 | 检索表格里的关键单元格文字,看上下文是否串行 |
| Notion 数据库属性 | 富文本属性只读到开头一段(如「Hello world」加粗后只剩「Hello」) | 用带格式标题的属性原文检索,比对截断 |
| .xls | 含双引号的单元格破坏行结构,产生错乱文本 | 检索含引号字段的数据行,看是否出现拼接错乱 |
# 快速抽查:在知识库检索测试框里,用原文件中
# 「只有正确提取才会出现的文本」做检索
# 例:CSV 里的一串完整编号 00123
# 命中 123.0 或查不到 → 该文档受影响,列入重导清单
Step 6:重新导入受影响文档
重导操作要点:
1. 删除受影响文档的现有索引(或整段知识库重建)
2. 重新上传原始文件 —— 修复后的提取器会正确处理
CSV:按文本读取,禁用缺失值推断(显式 csv_args 仍可覆盖)
Notion:单元格一段一列的错位已修正,属性完整拼接
3. 重导后用 Step 5 的抽查检索回归一遍
4. 在台账里登记:哪个库、哪些文档、何时重导、验证人
预期效果:重导后的检索命中正确文本(00123 还是 00123),Notion 表格检索结果与原文行列一致。把「重导清单」当项目管理——涉及多少文档、多少库,一批一批来,每批验证完再下一批。
重导有成本与副作用。大规模重导会触发重新嵌入(Embedding 费用与耗时随文档量走);删除重建期间该库检索可能不全。挑业务低峰执行,敏感库重导前先备份当前索引配置(分段参数、检索设置),别让重导顺手把调好的参数也冲掉了。
常见问题速查
| 你遇到的现象 | 大概率原因 & 解决 |
|---|---|
| 升级后原有集成突然 403 | 有人在面板里把存量 Key 改绑到了单库。存量 Key 本应保持未绑定行为;确认变更来源并恢复或改发新 Key |
| 按库 Key 访问自己绑的库也 403 | Key 绑错了库,或请求里的 dataset ID 与绑定库不一致。核对作用域选择器与 ID |
| 重导后检索还是错文本 | 只更新了文件没有删除旧索引,或重导的是新副本、命中的还是旧文档。确认删除旧索引后重导 |
| CSV 数字字段重导后变字符串 | 修复后的提取器按文本读取是有意行为。业务上确需数值类型时,用显式 csv_args 指定解析方式 |
| 找不到知识库的 API 访问面板 | 版本过旧或权限不足。升级到含按库授权的版本,并确认拥有该库的管理权限 |
| 重导后答案质量反而下降 | 分段参数没跟随原文档迁移。重导前备份分段与检索配置,逐项核对 |