指南

如何保障应用中 API 密钥的安全

要保障 API 密钥的安全,请把它们保存为托管平台上的机密或环境变量,只在服务端代码中使用,并且绝不要把它们粘贴到聊天、代码文件、截图或 Git 代码仓库中。为每个密钥只授予它所需的最小权限,在服务商处设置消费上限;如果某个密钥曾经泄露,就轮换它,即创建一个新的并删除旧的,而不是只是把它藏起来。

API 密钥就是服务的密码。你的 OpenAI 密钥可以让别人花你的钱使用 AI;你的 Stripe 私钥可以让别人发起退款;你的邮件服务商密钥可以让别人以你的名义发送邮件。AI 应用构建器很擅长把这些密钥接入应用,却不总是足够小心它们最终会出现在哪里,因此本指南介绍如何保障它们的安全,以及如何进行检查。

公开密钥与私密密钥

并非所有密钥都是机密的。了解二者的区别,可以避免你为错误的密钥恐慌,又忽视了真正需要保护的那个。

类型示例能否放在浏览器中?
可公开密钥 / 公开密钥Stripe 的 pk_… 密钥、限定域名使用的地图密钥、部分分析工具 ID可以,这是设计用途
私密密钥Stripe 的 sk_…、OpenAI 和 Anthropic 密钥、邮件服务商密钥、数据库密码绝不可以
服务或管理员密钥能够绕过托管数据库访问规则的密钥绝不可以,应视为最敏感的密钥

如果你不确定某个密钥属于哪一类,请查阅服务商的文档。拿不准时,就把它当作私密密钥处理。

第一步:把密钥保存为机密,而不是写在代码里

密钥应当放在托管平台的环境变量或机密设置中。你的代码在运行时通过名称读取它们(例如 process.env.OPENAI_API_KEY),这样密钥的值就永远不会出现在你的文件中。背景知识请参阅什么是环境变量和机密。

把每一个 API 密钥从代码中移到环境变量里。列出你找到的每个密钥、它原来所在的文件,以及你使用的变量名。不要显示它们的值。

然后检查是否还有遗漏:

搜索整个项目,包括配置文件和任何 .env 文件,查找看起来像 API 密钥或密码的内容。请报告文件和行号,而不是值本身。

第二步:私密密钥只在服务端使用

这是最重要的规则。浏览器接收到的任何内容,访问者都可以读取。页面源代码和 JavaScript 文件在开发者工具中都是可见的。

因此,如果应用需要调用 OpenAI,浏览器应该调用你的服务器,由你的服务器使用密钥调用 OpenAI。密钥永远不会离开服务器。

聊天功能目前直接从浏览器调用 OpenAI。把这个调用移到服务端 API 路由中,该路由从环境变量读取 OPENAI_API_KEY。浏览器只应调用我们的路由。该路由要求用户登录。

在前端框架中,有一个常见陷阱需要留意:带有公开前缀的变量,例如 Vite 中的 VITE_、Next.js 中的 NEXT_PUBLIC_,它们会被有意地打包进浏览器代码。即使私密密钥“保存在环境变量里”,只要带上这些前缀,它也会暴露出去。

第三步:测试是否有泄露

不要想当然地认为已经生效,请检查线上网站:

  1. 在浏览器中打开已发布的应用。
  2. 打开开发者工具,然后切换到 Sources(源代码) 或 Network(网络) 标签页。
  3. 在各个文件中搜索每个私密密钥的前几个字符(例如 sk_ 或 sk-)。
  4. 检查应用发出的网络请求。如果请求直接从浏览器发送到付费的 AI 服务商,这就是一个危险信号。

如果发现私密密钥,请把它移到服务端(第二步),并轮换它(第六步),因为它已经处于公开状态。

第四步:限制每个密钥的权限

许多服务商允许你限制密钥:

  • 有范围或受限的密钥,只能执行你的应用所需的操作。例如,Stripe 支持带有特定权限的受限密钥。
  • 域名或 IP 限制,适用于必须公开的密钥,例如地图密钥。
  • 为每个应用和每个环境分别使用独立的密钥,这样一次泄露不会暴露所有内容,撤销其中一个也不会影响其他密钥。
  • 开发时使用测试密钥,只在已发布的应用中使用正式密钥。

第五步:为损失设置上限

即使是保护得很好的密钥,也可能通过你自己的应用被滥用,例如有人编写脚本,对你的 AI 功能进行数千次调用。

  • 在每一个收费的服务商处设置消费上限或提醒。
  • 对任何按次收费的功能,要求登录。
  • 添加针对每位用户的速率限制。参见什么是速率限制。

为 /api/chat 添加限制:每位用户每小时最多 30 次 AI 请求。达到限制时返回清晰的提示信息。拒绝未登录用户的请求。

第六步:轮换泄露的密钥

如果私密密钥出现在了不该出现的地方(聊天消息、提交记录、截图、支持工单、浏览器代码),请假定它已经被泄露。

  1. 在服务商处创建一个新密钥。
  2. 在应用的设置中更新机密。
  3. 重新部署或重新发布,使线上应用使用新密钥。
  4. 在服务商处删除旧密钥。
  5. 检查服务商的用量日志,看看是否有你不认识的活动。

删除聊天消息或 Git 提交是不够的。Git 历史会保留旧版本,而任何公开过的内容可能早已被复制。

常见错误

  • 把密钥粘贴进提示词。 它现在就存在于聊天记录中了。请改用机密表单。
  • 私密变量带有公开前缀。 VITE_OPENAI_API_KEY 会把密钥发给每一位访问者。
  • 提交了 .env 文件。 在首次推送之前,确保它已被列入 .gitignore。
  • 所有地方都使用同一个密钥。 测试和正式环境、每个应用,都应使用独立的密钥。
  • 没有消费上限。 泄露或被滥用的、没有上限的密钥,可能在你注意到之前就已经产生巨额账单。
  • 隐藏而不是轮换。 密钥一旦暴露,只有更换新密钥才能解决问题。
  • 截图中包含密钥。 在分享设置页面寻求帮助之前,请裁剪或模糊处理。

检查清单

  • 每个密钥都保存为机密或环境变量,而不是写在代码里。
  • 没有任何 .env 文件或密钥被提交到 Git。
  • 私密密钥只用于服务端代码。
  • 没有私密变量使用 VITE_ 或 NEXT_PUBLIC_ 等公开前缀。
  • 我已在线上网站的 JavaScript 中搜索了每个密钥的前缀,没有找到任何内容。
  • 在服务商支持的情况下,密钥已设置范围或限制。
  • 测试和正式密钥是分开的。
  • 按次收费的功能需要登录,并设有针对每位用户的限制。
  • 每个收费的服务商都设有消费上限或提醒。
  • 我知道如何轮换每个密钥,并且任何曾经暴露的密钥都已轮换。

在 Mythex 中保障密钥安全

Mythex 通过两种方式让密钥远离你的代码和聊天:

  • 机密请求卡片。 当智能体需要密钥时,它会在聊天中显示一张卡片,你在表单字段中输入值,而不是在消息输入框中输入,该值会保存为项目机密。参见聊天中的机密。
  • 项目设置 → 机密,或聊天中的 /secrets,用于由你自己添加或修改密钥。参见环境变量与机密。

为已发布的应用更改机密之后,请重新发布,以便线上应用获取新值。导出的项目不包含机密,因此在你下次运行代码的任何地方,都需要重新添加它们。如果密钥曾经出现在聊天中,请在服务商处轮换它。

关于上线前的其余安全检查,请完整走一遍AI 构建应用安全检查清单。如果你正在添加 AI 功能,如何使用 LLM API会更深入地讲解密钥和成本问题。

常见问题

把 API 密钥放在前端代码里安全吗?

只有当服务商设计该密钥就是用于公开时才安全,例如 Stripe 的可公开密钥,或是限定在你域名下使用的地图密钥。任何能够消费金钱或读取私密数据的密钥,都必须留在服务端,因为发送到浏览器的任何内容都可能被任何人读取。

如果我把 API 密钥粘贴到了聊天或公开代码仓库中,该怎么办?

轮换它:在服务商处创建一个新密钥,更新应用的机密,重新发布,然后删除旧密钥。仅仅删除消息或提交记录是不够的,因为副本可能已经存在。

API 密钥应该存放在哪里?

存放在你的托管平台的环境变量或机密设置中,由服务端代码在运行时读取。它们不应被写入源文件、提交到 Git,或出现在截图中。

如何判断我的 API 密钥是否在网站中暴露了?

打开你的线上网站,在浏览器开发者工具中查看页面源代码和 JavaScript 文件,然后搜索密钥的开头部分。如果找到了,就说明它已暴露,应当将其移到服务端并轮换。

Mythex · Pricing · 用 AI 构建任何东西 · 网站和应用模板 · Mythex 对比 · AI 应用构建术语表 · 免费的 AI 应用构建工具 · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 繁體中文(香港) 繁體中文(台灣)