API 密钥与凭证管理

面向开发者的凭证形态之一:用于识别调用方而非认证具体用户;要支持签发、轮换、吊销与最小权限绑定,密钥只存哈希、不明文落库。

API 密钥的定位

API 密钥是面向开发者的凭证形态:它用来识别“调用方是哪个应用”,而不是认证“哪个用户正在操作”。因此它适合服务端到服务端的集成与配额归属,不适合放进浏览器或移动端代码里。一个可持续的密钥体系要支持签发、轮换、吊销与权限绑定四件事,并且只把密钥的哈希存在服务端——明文只在创建时展示一次。

基本信息

签发按应用签发,绑定权限范围与配额
存储服务端存哈希;仅在创建时展示一次明文
治理定期轮换、异常调用审计、离职与下线回收
辨识密钥前缀加环境标识,便于日志里快速定位泄漏来源

典型使用场景

  • 开放平台的开发者接入:按应用签发密钥并绑定调用配额
  • 服务端到服务端集成:内部系统与第三方系统之间的固定凭证
  • 计费与限流归属:按密钥统计调用量,用于配额与账单
  • 灰度或试用版本:给特定调用方单独签发可随时吊销的凭证
  • 数据同步任务:定时任务使用独立密钥,便于审计与单独吊销

密钥治理清单

  • 签发:按应用与用途签发,绑定权限与配额
  • 存储:服务端只存哈希,明文仅展示一次
  • 轮换:到期前双密钥并行,平滑切换
  • 吊销:即时生效并保留历史调用审计
  • 传输:仅通过 TLS,禁止出现在 URL 查询串里
  • 审计:记录调用方的密钥标识与来源 IP,便于异常追溯

校验流程(伪代码)

校验流程(伪代码)
key = read_header('Authorization')
if not key.startsWith('sk_live_'): return 401
row = db.find_by_hash(sha256(key))       # 只按哈希查库
if not row or row.revoked_at is not None: return 401
if not row.scopes.contains(required_scope): return 403
rate_limit(row.app_id, row.quota)         # 配额按应用维度统计
# 日志只记录密钥前缀与哈希前若干位,绝不记录完整密钥

常见风险与对策

风险表现对策
明文落库数据库或备份泄漏即全面失守只存哈希,明文仅创建时展示
权限过大一个密钥能调所有接口,无法按调用方审计按应用绑定最小权限范围与配额
无法轮换更换密钥需要调用方停机改配置支持双密钥并行期,平滑替换
写入仓库或前端密钥随代码或页面传播到不受控环境服务端调用,密钥走环境变量或密钥管理服务
无吊销与审计离职或应用下线后凭证仍然有效提供即时吊销入口并保留调用审计
API Key 放进前端或仓库会泄露;公开场景优先用带用户上下文的 OAuth/OIDC 方案,密钥只用于服务端之间的固定身份。
密钥出现在 URL 查询串里会被网关、代理与浏览器历史记录留存:认证信息必须走请求头,日志与监控里也要对密钥做脱敏。

易错点

  • 密钥明文存库并出现在日志,泄露面从单个应用扩大到全平台
  • 一个密钥全权限通用,无法按调用方审计与限流,出问题时难以定位与止损
  • 无轮换机制,密钥长期不变,人员变动后仍可继续调用
  • 吊销不即时生效:存在缓存或长连接复用,已吊销密钥仍能调用一段时间
  • 前端或移动端代码里内置密钥,被抓包提取后无法区分正常与恶意调用

数据来源与参考

  • OWASP API Security Top 10(2023):API2 Broken Authentication
  • Google API 设计指南:Authentication
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌