跳转到主要内容

API 密钥

本文约需 2 分钟阅读

API 密钥是一种用于在应用程序之间的通信中识别调用方的唯一字符串。在访问 Web 服务或云平台提供的 API 时,将 API 密钥包含在请求中,服务器即可判别「是谁在调用这个 API」。不过,严格来说 API 密钥是识别 (identification) 而非认证 (authentication) 的手段,需要理解它与 OAuth 令牌那样的精细权限控制存在根本性的不同。

API 密钥的工作原理

API 密钥的发送方式主要有 2 种。第一种是包含在请求头中的方式,像 <code>Authorization: Bearer sk-xxxx</code> 或 <code>X-API-Key: xxxx</code> 那样嵌入 HTTP 头中。第二种是作为查询参数附加到 URL 上的方式 (<code>?api_key=xxxx</code>),但由于密钥会残留在服务器日志和浏览器历史中,如今出于安全考虑已不推荐。即便采用请求头方式,如果通信未通过 TLS 加密,密钥也会以明文形式传输,因此使用 HTTPS 是基本前提。

API 密钥与 OAuth 令牌的区别

API 密钥是表示「这个请求来自哪个应用程序」的标识符,通常是固定的字符串。而 OAuth 的访问令牌则是表达「哪个用户、以何种范围 (权限范围)、授予了有效期至何时的授权」的动态令牌。API 密钥一旦泄露,与该密钥关联的所有操作都有被无限制执行的危险,而 OAuth 令牌则可通过范围限定和有效期将受害范围局部化。在实务中,通常将 API 密钥用于公开 API 的用量限制,将 OAuth 令牌用于访问用户数据,二者区分使用。

密钥泄露事故的实态

API 密钥泄露是开发现场最频繁发生的安全事件之一。将 AWS 的访问密钥提交到 GitHub 的公开仓库,在数分钟内便被自动扫描机器人检测到并被滥用于加密货币挖矿的案例层出不穷。2023 年,某企业因将 API 密钥粘贴到 Slack 消息中,最终演变为大规模的数据泄露。AWS 引入了自动检测并使 GitHub 上泄露密钥失效的机制,但在检测前的短暂时间差内仍有发生损害的情况。在初创企业的安全检查清单中,密钥管理也被列为最优先事项。

机密管理的最佳实践

将 API 密钥直接写入源代码 (硬编码) 是最危险的反模式。作为替代,最低限度的措施是用环境变量 (<code>.env</code> 文件) 管理密钥,并通过 <code>.gitignore</code> 将其排除在 Git 的跟踪对象之外。在更稳健的运维中,会使用 HashiCorp Vault 或 AWS Secrets Manager 这类机密管理服务。这些服务提供密钥的静态加密、访问日志记录、自动轮换等功能,可以安全地管理密钥的整个生命周期。作为密钥管理的基本原则,将能够访问密钥的人员和系统限定为最小权限非常重要。

机密管理的实践方法,API 安全书籍 (Amazon)中也有体系化的讲解。

轮换的重要性

API 密钥应当定期更换为新的 (轮换)。密钥已泄露却未被察觉的情况很多,定期轮换作为限定「未被察觉的泄露」受害期间的保险而发挥作用。AWS 和 Google Cloud 推荐每 90 天轮换一次,并提供自动轮换功能。轮换时,通过设置旧密钥和新密钥在一定期间内均有效的「宽限期」,可防止服务中断。也请参考API 密钥管理详解指南

常见的误解

「只要有 API 密钥安全就万无一失」这一误解根深蒂固,但 API 密钥只是一个标识符,仅凭它并不能提供充分的保护。除 API 密钥外,结合 IP 地址限制、速率限制、来源检查等的纵深防御不可或缺。此外,若将 API 密钥嵌入前端的 JavaScript 中,任何人都能通过浏览器的开发者工具查看,因此原则上应采用仅在服务器端处理密钥的设计。

相关术语

这篇文章对您有帮助吗?

XHatena