什么是环境变量和密钥?通俗指南
环境变量是一个有名字的设置,比如 DATABASE_URL 或 STRIPE_SECRET_KEY。应用运行时,它会被交给应用,而不是写死在代码里。密钥则是一种必须保密的环境变量,它的值包括 API 密钥、密码或签名密钥。把这些值放在代码之外,意味着你无需修改应用就能更换它们,可以在测试和真实客户使用不同的值,并且在分享或发布代码时避免它们泄露。
用 AI 做应用时,为什么这很重要
只要你的应用要和其他服务打交道(收款、发邮件、调用 AI 模型),它就需要密钥。AI 应用生成工具经常会要求你提供这些密钥,而密钥最终放在哪里,决定了你的应用是否安全。
AI 生成的应用里,有两类问题很常见:
- 密钥被粘贴到聊天或代码里。 它于是会留在聊天记录、项目文件以及任何导出或代码仓库中。任何看到它们的人都能使用你的账户。
- 密钥在浏览器里被使用。 如果调用 Stripe 或 OpenAI 的代码在页面中运行,密钥就会发送给每一位访客。确实有人会查看,自动化扫描器也在不断地寻找暴露的密钥。
理解环境变量,能帮你识别这两类问题,并要求对方修复。
日常类比:酒店保险箱
你应用的代码就像酒店房间,客人(以及清洁工,以及任何你给了门卡的人)都会进出。你不会把护照放在桌上。
环境变量就像房间里的保险箱。房间知道保险箱的存在,也知道需要时如何打开,但护照并不会随处乱放。如果你从测试环境搬到正式网站,只需要在那个房间的保险箱里放入另一本护照,无需重新装修。
工作原理
你的代码引用的是一个名字,而不是具体的值。在服务器端的 JavaScript 中,写法类似 process.env.STRIPE_SECRET_KEY。应用启动时,它所运行的平台会为这个名字填入对应的值。你在平台设置中修改这个值,然后重启或重新部署,应用就会使用新的值,无需改动代码。
这些值的来源取决于应用运行的位置:
| 运行位置 | 值保存在哪里 |
|---|---|
| 开发者的笔记本电脑 | 通常是名为 .env 的本地文件,绝不能提交到 git |
| AI 生成工具的预览环境 | 项目的密钥或设置面板 |
| 托管平台 | 该平台的环境变量设置 |
| GitHub Actions 或其他自动化工具 | 该服务自带的加密密钥库 |
公开变量与密钥
并非所有环境变量都是机密的。可以把它们分成两组:
| 类型 | 示例 | 浏览器能看到吗? |
|---|---|---|
| 公开配置 | 网站名称、公开的分析 ID、Stripe 可公开的(publishable)密钥、功能开关 | 能,这没有问题 |
| 密钥 | Stripe 私密(secret)密钥、OpenAI 或 Anthropic 的 API 密钥、数据库连接字符串、邮件服务密钥、Webhook 签名密钥 | 绝不能 |
各类 Web 框架会明确地区分这两者。在 Vite 中,只有名称以 VITE_ 开头的变量会被打包进浏览器代码;在 Next.js 中,前缀是 NEXT_PUBLIC_。这是一项安全机制:带有这些前缀的内容会进入每位访客都会下载的文件,因此密钥绝不能使用这类前缀。
实际例子:AI 摘要按钮
假设你想要一个“总结这条笔记”的按钮,它会调用 AI 模型。
不安全的做法: 按钮的代码在浏览器中运行,并把 API 密钥直接写在代码里,去调用 AI 服务商。它在预览中能正常工作,但任何人都可以打开浏览器的开发者工具,复制这个密钥,然后用你的账户产生费用。
安全的做法:
- 你在 AI 服务商处创建密钥,并在项目设置中将其保存为名为
OPENAI_API_KEY(或类似名称)的密钥。 - 后端新增一个路由
POST /api/summarise,它读取process.env.OPENAI_API_KEY,检查用户是否已登录,然后调用服务商。 - 按钮调用的是你自己的路由,而不是服务商。浏览器永远看不到这个密钥。
- 你把同一个密钥添加到已发布应用的设置中并重新部署,这样线上网站也能使用它。
这种模式(浏览器调用你的服务器,服务器保管密钥并调用服务)适用于支付、邮件、地图以及其他所有付费 API。LLM API 使用指南会更深入地讲解 AI 的情况。
关键术语
.env文件: 一个由名称=值每行组成的文本文件,用于本地开发。将它列入.gitignore,避免被提交。.env.example: 只包含名称、不含真实值的副本。它会被提交,让其他人知道需要设置哪些变量。- 轮换(Rotate): 用新的密钥替换旧的密钥,并撤销旧密钥。
- 权限范围(Scope / permissions): 许多服务商允许你创建只能执行特定操作的密钥。只能发送邮件的密钥,比能做任何事的密钥危险性更低。
- 测试密钥与正式密钥: Stripe 等服务商会为测试和真实收款分别提供密钥。在正式上线前使用测试密钥。
- 签名密钥(Signing secret): 用于验证某条消息(比如 Webhook)确实来自发送方的密钥。
常见错误与误解
- “我的代码仓库是私有的,所以里面放密钥没问题。” 私有仓库同样会被分享、复刻、导出并克隆到笔记本电脑上。密钥依然不应该放在那里。如果你把项目连接到 GitHub,请检查其中是否包含
.env文件。 - “我删掉了,所以它就没了。” Git 会保留历史记录,聊天日志也会保留消息。如果密钥曾经暴露过,就应该轮换它。
- 给密钥使用了公开前缀。
VITE_OPENAI_KEY会把你的密钥放进浏览器代码包里。 - 忘记重新部署。 在设置中修改变量,通常要等应用重启或重新发布后才会生效。
- 所有地方共用一个密钥。 为测试和正式环境、以及每个应用分别使用独立的密钥,这样才能在不影响其他应用的情况下撤销其中一个。
- 没有消费上限。 对于收费的 API,请在服务商后台设置预算或限额,以防密钥泄露。
向 AI 生成工具提出的要求
- “从名为
STRIPE_SECRET_KEY的环境变量中读取 Stripe 私密密钥,只在服务器端使用。” - “确保任何密钥都不会用于客户端代码,也不要给它加上
VITE_或NEXT_PUBLIC_前缀。” - “创建一个
.env.example,列出应用需要的所有变量但不包含值,并确保.env被 git 忽略。” - “检查构建后的前端文件,看看是否有任何看起来像 API 密钥的字符串。”
我们的 AI 生成应用安全检查清单,会和其他上线前检查项一起涵盖密钥相关的内容。
Mythex 中的密钥
在 Mythex 中,密钥是项目环境变量,会同时注入到预览沙盒和已发布的应用中。你可以在 项目设置 → Secrets 中添加,也可以在聊天中使用 /secrets 命令添加。当智能体需要某个密钥时,它会在聊天中显示一张密钥卡片,因此密钥值会被输入到表单字段中,而不会出现在消息记录里。如果你修改了正式应用的密钥,请重新发布,部署才会应用新的值。项目导出不包含密钥,导入的 .env 文件中的密钥也会被剔除,你需要在设置中重新添加。详情请参阅文档中的环境变量和密钥以及聊天中的密钥。
常见问题
什么是环境变量?
环境变量是一个有名字的设置,比如 STRIPE_SECRET_KEY 或 DATABASE_URL,它在程序运行时交给程序,而不是写死在代码里。同一份代码因此可以在开发环境和正式环境中使用不同的值。
环境变量和密钥有什么区别?
密钥是一种必须保密的环境变量,比如 API 密钥、数据库密码或 Webhook 签名密钥。其他环境变量,比如网站名称或功能开关,可以是公开的。
把 API 密钥放在前端安全吗?
不安全。前端代码会被下载到每一位访客的浏览器里,任何人都能读取。密钥只能在服务器端使用,浏览器应该调用你自己的服务器,再由服务器去调用服务提供方。
API 密钥泄露了怎么办?
立即在服务提供方那里撤销或轮换该密钥,生成一个新的,在你的应用保存密钥的地方更新它,然后重新部署。仅仅从代码或聊天记录里删除密钥是不够的,因为副本可能已经存在。