BYOK(Bring Your Own Key,用户自带密钥)指用户把自有 AI 服务商的 API 密钥接入网关,网关代理调用、用户在服务商侧直接结算,密钥明文只在网关内存中短暂存在。我们在企业级 AI 网关(Spring Boot + Spring AI + 多模型接入 + SSE 对话网关)中落地 BYOK 时,核心做了三件事:密钥入库前用信封加密(AES 数据密钥 + KMS 包装主密钥)、调用时从内存取用并拦截一切日志输出、提供一键轮换与撤销。下面拆解完整实现。
一、BYOK 与平台代管密钥的差异
两种模式的本质区别是”谁持有密钥、谁向服务商买单”。
| 维度 | 平台代管密钥 | BYOK 用户自带密钥 |
|---|---|---|
| 密钥归属 | 平台统一采购 | 用户自有 |
| 结算对象 | 平台向用户收费 | 服务商直接向用户收费 |
| 模型权限 | 平台配置的模型 | 用户账号下的全部模型 |
| 合规要求 | 平台兜底 | 用户合同与合规自查 |
| 网关价值 | 聚合计费、统一管理 | 统一接入、可观测、无加价 |
BYOK 的价值在聚合:用户已有 OpenAI、Anthropic 等账号的订阅套餐或专属合同,把密钥接入网关后,仍然走网关的统一鉴权、限流、计费监控与 SSE 转发,模型调用却记在用户自己头上,网关只按用量收取路由费用。用户侧还看重一点:BYOK 能立刻用上服务商新发布的模型,不用等平台接完。
二、密钥的加密存储
密钥不能落明文库。我们采用信封加密:随机生成数据密钥 DEK 加密密钥明文,DEK 再用 KMS 包装的密钥加密后落库。密钥被拆成两份存储,单独拖库也还原不出明文。
public class KeyCipher {
// keyId 用于关联 KMS 包装密钥,用于解密 DEK
public EncryptedKey encrypt(String plainKey) {
byte[] dek = KeyGenerator.generateAesKey(); // 随机 DEK
byte[] ciphertext = aesEncrypt(plainKey, dek); // DEK 加密明文
byte[] wrappedDek = kmsClient.wrap(dek); // KMS 包装 DEK
return new EncryptedKey(Base64.encode(ciphertext),
Base64.encode(wrappedDek));
}
}
落库字段包括密文、包装后的 DEK、provider、创建时间、状态与别名。解密只在调用瞬间于内存完成,用完即弃,禁止写入任何日志与追踪上下文。
三、密钥接入与校验流程
用户通过管理台或配置接口提交密钥,走五步:
- 前端收集密钥,仅经 HTTPS 提交,浏览器本地不做持久化;
- 后端按 provider 校验格式,如 OpenAI 的 key 以
sk-开头且长度 20 位以上,格式不符直接拒绝; - 用该密钥向对应服务商发一次最小成本探测请求,验证有效性;
- 通过后信封加密落库,状态置为 active,回显只显示掩码(如
sk-****abcd); - 写入密钥审计日志,记录操作人与时间,不记录密钥内容。
四、请求时如何取用密钥
网关转发请求时按”用户 > 模型 > provider”查找密钥,解密后放进内存变量,拼到上游 Authorization 请求头。两个硬约束:密钥不落访问日志,异常堆栈里出现密钥一律脱敏;响应侧不得回显密钥字段。多实例部署时密钥缓存放本地内存,配合版本号刷新,轮换后短时间生效。
五、密钥轮换与撤销
轮换不能删旧键:新请求用新密钥,在途请求走完旧密钥,灰度迁移窗口内两个版本并存。用户加一个新密钥后把旧密钥标记 revoked,系统对新请求自动切新密钥,旧密钥按策略定期清除。撤销走相同流程,标记后 15 分钟内禁止继续放行。整个过程对调用方透明,业务代码不用改。
六、SSE 对话网关的适配
BYOK 与 SSE 组合时多一个细节:流式请求中途上游返回 401 密钥失效,网关不能简单终止,要回放错误事件到客户端并记录告警,同时把该密钥状态自动置为 invalid,提示用户轮换。我们加了一个探活定时任务,周期性用密钥做轻量探测,失效密钥提前暴露,而不是等到用户调用时才爆。
七、落地踩坑
密钥校验请求要控制频次,防止用探测接口做暴力枚举。加密密钥的 KMS 权限要最小化,应用只保留 wrap/unwrap 两个动作。密钥归属审计不能省,BYOK 模式下出问题要能追溯”哪个密钥、哪次调用、哪个操作人”。最容易被忽视的是密钥泄露的兜底:日志采集、异常上报、监控平台这三条出口都要配置脱敏,否则密钥一旦进日志就再也追不回。
常见问题(FAQ)
Q1:BYOK 的密钥放在网关里安全吗?
明文仅内存短暂存在,落库走信封加密,且日志与追踪全部脱敏。
Q2:BYOK 和平台代管能同时用吗?
能,按用户或模型维度配置优先级,缺省走平台密钥,BYOK 优先。
Q3:密钥失效了怎么办?
自动探测标记 invalid 并告警,用户换新密钥即恢复,不落库密文。