模型配置存进数据库后,API Key 在管理页面上怎么展示和修改?
简化版
列表和编辑接口都不返回完整的 API Key,只返回脱敏串:保留开头几位和结尾四位,中间用星号代替,管理员能认出是哪一把 Key,完整的 Key 却不会出现在页面、浏览器缓存和接口返回里;太短的 Key 全部打星。脱敏带来一个必须处理的问题:编辑弹窗里带出来的是脱敏串,管理员只改了模型名就点保存,脱敏串会跟着提交回来,直接存进库真 Key 就毁了。所以后端要识别「没改 Key」的情况:提交值里带星号或者为空,就沿用数据库里的原值,只有管理员真的输入了新 Key 才更新。测试连接、调用模型都在后端按主键读真 Key,完整的 Key 始终不出后端。
详细版
列表 / 编辑回显 后端返回脱敏串:sk-a********mnop
管理员只改模型名 表单里的 Key 还是脱敏串,一起提交
后端保存 提交值含星号或为空 -> 沿用库里的原 Key
提交值是新输入的 Key -> 更新
测试连接 前端只传配置主键,后端按主键读真 Key 发请求
| 环节 | 要做到 | 做不到的后果 |
|---|---|---|
| 列表接口 | 只返回脱敏串 | 完整 Key 出现在页面、网络面板和浏览器缓存里 |
| 编辑保存 | 识别脱敏串和空值,沿用原 Key | 脱敏串被存进库,下一次调用报 Key 无效 |
| 页面提示 | 写明「留空表示不修改原密钥」 | 管理员以为必须重新输入 Key |
| 测试与调用 | 后端按主键读真 Key | 为了测试把 Key 传回前端,脱敏形同虚设 |
完整版教学
一、为什么列表接口不能返回完整 Key
模型配置页是管理员天天打开的页面。如果列表接口把完整 Key 原样返回,它会出现在很多意想不到的地方:
| 位置 | 怎么泄露 |
|---|---|
| 页面本身 | 共享屏幕、截图、录屏教程 |
| 浏览器开发者工具 | 网络面板里的接口响应一目了然 |
| 浏览器缓存、代理日志 | 响应体被缓存或记录 |
| 前端错误上报 | 带着表单数据的报错被发到监控平台 |
API Key 泄露的代价是真金白银:别人拿它调用模型,账单记在你的账户上。所以原则很简单:完整的 Key 只在后端和数据库之间流动,任何返回给前端的接口都不带它。
记忆钩子:Key 只进不出。页面能写入新 Key,但永远读不到完整的 Key。
二、脱敏规则:留多少、怎么留
脱敏不是把整串都换成星号,那样管理员分不清配的是哪一把 Key。常见做法是保留头尾:
def mask(api_key: str) -> str:
# 还没填过 Key 时返回空串
if not api_key:
return ""
# 太短的 Key 全部打星,避免露出有效片段
if len(api_key) <= 8:
return "*" * 8
# 保留前 4 位和后 4 位,中间固定 8 个星号
return api_key[:4] + "*" * 8 + api_key[-4:]
用一个 35 位的 Key 算一下:原 Key 35 个字符,脱敏后只露出 8 个字符,剩下 27 个字符不可见;中间固定用 8 个星号,而不是按原长度打星,连 Key 的长度也不暴露。前缀通常是服务商标识(例如 sk-),后四位足够让管理员和控制台里的 Key 列表对上号。
短 Key 的处理要小心:长度不超过 8 位时再「保留前 4 后 4」,就等于原样返回。所以短 Key 全部打星。
三、编辑时最容易踩的坑:脱敏串被存回去
脱敏解决了「读」的问题,却在「写」这里埋了一个坑:
1. 管理员打开编辑弹窗,表单里 api_key = "sk-a********mnop"(脱敏串)
2. 只把模型名从 qwen-plus 改成 qwen-max,点保存
3. 前端把整张表单提交,api_key 字段带着脱敏串
4. 后端直接 update,数据库里的真 Key 被替换成 "sk-a********mnop"
5. 下一次调用模型,服务商返回 401,Key 无效
这个 bug 很隐蔽:保存那一刻一切正常,问题要到下一次调用才暴露,而且报的是「Key 无效」,管理员会以为是 Key 过期了。
四、怎么判断「管理员没有改 Key」
后端要在保存时分清三种提交值:
| 提交值 | 含义 | 处理 |
|---|---|---|
| 含星号的脱敏串 | 没动这个输入框 | 沿用库里的原 Key |
| 空字符串 | 清空了输入框 | 沿用原 Key(或者按业务约定视为「不修改」) |
| 不含星号的新字符串 | 输入了新 Key | 更新 |
能用星号判断,是因为真实的 API Key 里不会出现星号;含星号的一定是脱敏串。空值也按「不修改」处理,这样表单上可以写一句「留空表示不修改原密钥」,管理员清空输入框也不会误删 Key。另一种设计是把 Key 从普通表单里拿出去,单独做一个「更换 Key」的按钮和弹窗,编辑其他字段时根本不提交 Key 字段,也能避免这个问题。
五、测试和调用都在后端取真 Key
脱敏之后,前端手上再也没有完整的 Key。所以「测试连接」只传配置主键,后端按主键从库里读出真 Key 发请求;业务调用同样由后端按用途取配置。不能为了测试方便,专门加一个返回完整 Key 的接口,那会让前面的脱敏全部失效。
测试用的是库里已保存的配置,也意味着:管理员新输入的 Key 要先保存,再点测试。这一点要在页面上讲清楚,否则管理员会以为「测试的是弹窗里刚输入的那一把」。
六、页面之外还要防的地方
Key 不出现在页面上,不等于不会泄露到别处:
- 调用日志不记 Key。 日志记配置 ID、服务商、模型名就够了,请求头里的
Authorization不要落库。 - 错误信息要截断。 服务商和框架的异常信息可能很长,写进日志和返回给页面前都要截断,只保留排查需要的部分。
- 接口权限要收紧。 模型配置的增删改查只给管理员,普通用户即使拿到接口地址也调不通。
七、和生产级密钥管理的差距
把 Key 存在业务数据库里、页面上脱敏,适合单体应用和学习项目。生产环境通常还要做:库里的 Key 加密存储、Key 放进专门的密钥管理服务、定期轮换、访问审计、按环境隔离。这些内容见「大模型应用中的密钥和工具凭证如何管理?」。页面脱敏和「编辑不覆盖」这两件事,无论后端怎么存 Key,管理页面都要做。
八、常见误区与追问
- 误区:脱敏就是把整串 Key 换成星号。 管理员需要认出是哪一把 Key,保留头尾几位更实用。
- 误区:前端做脱敏就够了。 接口返回的是完整 Key 的话,网络面板里照样看得到,脱敏必须在后端做。
- 误区:编辑时把表单原样提交、原样保存最简单。 脱敏串会覆盖真 Key,下一次调用才报错,很难排查。
- 误区:为了测试连接,返回一次完整 Key 没关系。 测试只需要传主键,后端自己取 Key,没有任何理由把 Key 返回前端。
- 追问:短 Key 为什么全部打星? 长度不超过 8 位时保留头尾各 4 位,等于把整串原样返回。
- 追问:为什么能用星号判断是不是脱敏串? 真实的 API Key 不含星号,含星号的提交值只可能来自脱敏后的回显。
九、加强记忆
API Key 在管理页面上「只进不出」:列表和编辑回显一律由后端返回脱敏串,保留头尾几位便于辨认,短 Key 全部打星;编辑保存时,提交值含星号或为空就沿用库里的原 Key,只有输入了新串才更新,页面写明「留空表示不修改」;测试连接和业务调用只传主键,由后端读真 Key。页面之外,日志不记 Key、错误信息截断、配置接口只给管理员。生产环境再往上加加密存储、密钥托管和轮换,但页面脱敏和编辑不覆盖这两件事始终要做。
项目实战落地
项目里怎么做的
《AI Agentic RAG高级企业知识库平台》的模型配置列表接口返回的是脱敏串:
def _mask(api_key: str | None) -> str:
"""密钥脱敏,只保留前 4 位和后 4 位。"""
if not api_key:
return ""
if len(api_key) <= 8:
return "*" * len(api_key)
return api_key[:4] + "*" * 8 + api_key[-4:]
编辑保存时,提交上来的 Key 只有「非空且不含 *」才会写进更新字段,否则跳过,数据库里的原 Key 不动;编辑弹窗的 API Key 输入框提示「留空表示不修改原密钥」。
《AI Agent智能会议纪要辅助系统》的规则略有不同:常规 Key 保留前 3 位和后 4 位,中间是 ****;不超过 8 位的 Key 一律返回 8 个星号。保存时提交值为空或含 ****,就把它还原成数据库里的原 Key,再拿还原后的真实值做启用校验和写库,掩码字符串不会存进数据库。
为什么这样取舍
- 保留头尾。 管理员要能认出这是自己配的哪一把 Key,整串打星就分不清了。
- 识别星号而不是比对原值。 真实的 Key 里不含星号,含星号的一定是页面回显的脱敏串,判断简单,也不用把原值拿去和提交值比。
- 清空也按不修改处理。 输入框被清空时同样沿用原 Key,避免管理员清空输入框后把 Key 误删。
- 短 Key 的两种打法。 知识库平台按原长度打星,纪要系统固定打 8 个星号,后者连长度也不暴露。
配置中心的其他两块,见「模型配置为什么要做成可动态修改的?连通性测试要测什么?」和「Prompt Registry 在 LLMOps 中解决什么问题?」。
面试官还会追问
- 知识库平台里,启用中的模型配置为什么不允许删除?要删的话得先做什么?
- 纪要系统里,已经被转写任务、纪要或自检运行用过的模型配置,为什么不能删除、也不能改用途?
学完《AI Agentic RAG高级企业知识库平台》,上面这些追问你都会迎刃而解。