API Key 安全架构设计:假设密钥一定会泄露

在 AI 推理服务平台中,API Key 是用户与平台之间的信任凭证。当 Key 泄露时,如何将损失降到最低?本文分享我们在 Token 服务平台安全架构上的设计思路与实践经验。


背景

我们正在构建一个兼容 OpenAI API 规范的 AI 模型推理服务平台,面向企业用户和个人开发者。在这个平台上,每一个 API 调用都通过一个 Token(即 API Key)进行身份认证。

Key 泄露是一个"不是会不会,而是什么时候"的问题。代码提交到公开仓库、员工误操作、第三方服务被拖库……任何环节都可能让 Key 流到不该去的地方。

传统做法是"防泄露"——但这就像只修堤坝不建排水系统。我们的思路是:假设 Key 一定会泄露,通过限制爆炸半径、快速发现、快速响应来将损失降到最低。


一、Key 设计:明文只出现一次

格式规范

Key 采用固定前缀 + 随机字符串的格式:

tkp-hVm7YfhlcRsddfKpNtZ0FVcbT3x9mQs

前缀 tkp- 是平台唯一标识,用于向 GitHub Secret Scanning 注册扫描规则。一旦确定不可更改,因为它影响所有存量 Key 的识别。

明文只出现一次原则

这是整个安全架构的基石:

用户申请 Key
    ↓
平台生成明文 Key
    ↓
   ┌─────────────────────┬─────────────────────┐
   ↓                     ↓                     ↓
实时展示给用户          存 Hash 到数据库      存末4位
(仅此一次弹窗)        SHA256,用于验证      用于列表页识别

数据库只存储 SHA256 哈希值和末 4 位明文。每次请求到来时,计算 Header 中 Key 的 SHA256,与数据库比对验证。

拖库?攻击者拿到的只有哈希值,无法还原原始 Key。

调用 Key 与管理 Key 分离

Key 类型 权限范围 使用场景
调用 Key 只能请求模型推理接口 嵌入业务代码、SDK 中
管理 Key 查用量、创建/禁用子Key、修改配置 管理员在控制台操作

调用 Key 泄露,最多被盗刷 Token;管理 Key 泄露,账户控制权不保。两类 Key 独立生成,互不通用。

禁用 vs 删除,一字之差天壤之别

  • 禁用:临时暂停,可重新启用,适合"临时不想用"
  • 删除:彻底消除,不可恢复,适合"Key 丢失或疑似泄露"

当用户说"我的 Key 好像丢了",回答是"删除旧 Key,重新申请新 Key"——而不是禁用。


二、访问控制:三层防护

第一层:IP 白名单(企业用户)

企业用户在控制台配置允许调用的 IP 或 CIDR 段:

192.168.1.100        # 单个 IP
10.0.0.0/8          # 企业内网段
203.0.113.0/24      # 办公室出口段

配置白名单后,来自白名单外的请求直接返回 403。未配置白名单的用户走异常检测兜底。

第二层:频率限制(Rate Limiting)

按套餐等级设置分层阈值:

套餐 RPM TPM 单日 Token 上限
免费/试用 10 10,000 100,000
标准版 60 100,000 5,000,000
企业版 300 500,000 合同约定

采用双阈值触发策略

正常 → [软阈值 80%:发告警,不拦截] → [硬阈值 100%:返回 429,停止服务]

软阈值时邮件通知客户,由客户判断是否异常;硬阈值时短信 + 邮件同步告警,当日剩余时间拒绝请求,次日 00:00 自动重置。

第三层:消费上限

用户可为每个 Key 单独配置 Token 消费上限:

  • 单次请求上限:防止单次超长请求
  • 单日上限:防止日间被盗刷
  • 单月上限:企业按部门/项目分配预算

典型场景:企业为各部门分发独立 Key,设置月度预算上限,超额自动停用。财务再也不用追着问"这个月 API 费用怎么这么高"。


三、异常检测:让攻击者无处遁形

地域异常跳变检测

不做国内/国外的二元过滤(VPN 用户会有大量误报),改为检测同一 Key 的地理位置一致性:

同一 Key 在滑动时间窗口(30分钟)内:
  来源城市 ≥ 3 个 → 中风险告警
  来源国家 ≥ 2 个 → 高风险告警 + 通知用户立即检查

实现非常简单:Redis Set + 30 分钟 TTL,每次请求将 IP 解析的城市写入,Set 大小超阈值即触发告警。

同 IP 多 Key 关联分析

一个 IP 使用多个不同 Key,这是一个强烈的风险信号:

Redis Key: ip:{ip}:keys → Set,存该 IP 使用过的 key_id(1小时 TTL)

检测规则:
  Set ≥ 3  → 低风险,记录日志
  Set ≥ 5  → 中风险,平台运营告警
  Set ≥ 10 → 高风险,自动封禁该 IP + 通知所有涉及 Key 的用户

正常用户一个 IP 只会用自己的 Key。同一 IP 使用大量不同 Key,说明有人在批量测试盗来的 Key。

Honeypot Key(蜜罐)

这是我最喜欢的一个设计。预先创建一批永远不分配给真实用户的假 Key,主动投放到容易被扫描的位置:

  • 官方文档示例代码
  • GitHub 示例仓库
  • 爬虫陷阱页面

当 Honeypot Key 收到任何请求时:

→ 记录来源 IP、时间、User-Agent、请求内容
→ 返回正常响应(不报错,避免攻击者知道触发了陷阱)
→ 将来源 IP 加入高风险 IP 池
→ 平台运营立即告警
→ 检查同时段该 IP 是否也在测试真实用户的 Key

关键点:返回正常响应而非报错——让攻击者继续暴露,而不是打草惊蛇。

行为基线

每个 Key 建立 30 天的使用基线:

工作日 09:00-18:00 → 平均 80 RPM
工作日 18:00-23:00 → 平均 20 RPM
凌晨 00:00-06:00   → 平均 2 RPM

当凌晨流量突然飙升到基线的 5 倍,系统自动告警。新 Key 前 7 天只采集数据不做告警,避免误报。


四、审计:每一笔调用都可追溯

request_id 串联全链路

Nginx 1.11.0+ 内置的 $request_id 变量是整个审计系统的基石:

location / {
    proxy_set_header X-Request-Id $request_id;  # 传给后端
    add_header X-Request-Id $request_id;         # 返回给客户端
}

应用层取出 request_id 记录到结构化日志中。两条日志通过 request_id 关联,用于事后溯源。

日志不可篡改

应用层实时写日志
  → 写入本地文件(缓冲)
  → 异步上传到对象存储(OSS/S3)
  → 对象存储设置只读策略(上传后不可修改删除)
  → 本地文件定期清理

或直接使用云日志服务(阿里云 SLS / 腾讯云 CLS),天然不可篡改且支持检索。


五、安全控制台:把枪交到用户手里

用户不需要联系客服就能处理大部分安全问题:

功能 说明
调用日志查询 按时间、Key、模型、状态筛选,支持导出
实时用量图表 Token 消耗趋势,RPM/TPM 实时监控
异常事件列表 平台检测到的异常记录
一键禁用/删除 Key 秒级生效,紧急响应
IP 白名单 企业用户自主配置
消费上限 单日/单月 Token 上限
Webhook 企业版,异常事件回调到自有监控系统

一键吊销的实现路径:

用户点击"禁用" / "删除"
  → 立即更新数据库状态
  → 同步更新 Redis 缓存(秒级生效)
  → 后续请求验证时命中缓存,直接返回 401

六、GitHub Secret Scanning 联动

这是 GitHub 提供的免费服务。平台注册后,GitHub 会自动扫描所有公开仓库中的 Key 格式,发现匹配时回调通知平台。

注册流程:

  1. 加入 GitHub Secret Scanning Partner Program
  2. 提供 Key 识别正则:tkp-[A-Za-z0-9]{20,40}
  3. 提供告警回调 URL
  4. GitHub 审核通过后自动生效

回调处理逻辑:

GitHub POST 回调(包含 Key 片段、仓库地址、提交者信息)
  → 验证回调签名(防伪造)
  → 查找匹配的 Key
  → 自动禁用该 Key
  → 立即通知对应用户(邮件 + 短信)
  → 记录安全事件日志

注意:前缀一旦确定不可更改,所有存量 Key 的扫描规则都基于此前缀。


实施路径

第一阶段:立即实施

  • Key Hash 存储 + 明文仅展示一次
  • 调用 Key / 管理 Key 分离
  • 一键吊销 Key(秒级生效)
  • 完整调用日志 + RPM/TPM 频率限制
  • 消费上限配置

第二阶段:短期实施

  • IP 白名单(企业用户)
  • 地域跳变检测 + 关联分析
  • 软阈值告警(邮件 + 短信)
  • GitHub Secret Scanning 联动

第三阶段:中期实施

  • 行为基线建立(需 30 天数据积累)
  • Honeypot Key 投放
  • 自助安全控制台完善
  • 日志归档到对象存储

最后:关键设计原则

  1. 假设 Key 一定会泄露 — 限制爆炸半径 + 快速发现 + 快速响应
  2. 明文只出现一次 — 数据库永远不存 Key 明文
  3. 最小权限原则 — 调用 Key 和管理 Key 严格分离
  4. 兼容 OpenAI 规范 — 不引入破坏性改造
  5. 用户自主可控 — 控制台提供足够的自助安全工具

安全不是一道城墙,而是一套体系。当每道防线都失效时,还有下一道防线在等你。这就是纵深防御(Defense in Depth)的核心思想。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐