前端如何安全存储 API 密钥 —— 两种实用方案
前端如何安全存储 API 密钥 —— 两种实用方案
在前端开发中,我们经常需要调用第三方 API(例如 OpenAI、DeepSeek、Google API 等)。
这些 API 通常需要密钥(API Key)来验证身份。
问题是:如果你把密钥直接写在前端代码里,一旦上线,就等于公开给全世界看。
本篇文章介绍 两种安全存储前端 API 密钥的方法,让你在项目中都能拿出一个专业答案。
问题背景
- 前端代码最终会被打包成 JS 文件,所有变量在浏览器里都能被看到
- 即使你写在
.env
文件里,只要变量被打包进前端,别人仍然可以在浏览器调试工具里看到 - 所以不能在浏览器端直接使用敏感密钥
- 解决办法就是:不让密钥出现在客户端
方案 1:环境变量 + 构建时注入(推荐,适用于无需完全隐藏的情况)
原理
- 密钥不直接写在源码里,而是写在
.env
或云平台的环境变量里 - 构建时(build)将密钥注入到打包代码中
- 优点是简单,适合非核心密钥(比如公开 API、统计工具等)
使用示例(Vite 项目)
-
本地
.env
文件(不会提交到 GitHub)VITE_API_KEY=xxxxxx
-
代码中引用
const apiKey = import.meta.env.VITE_API_KEY fetch(`https://api.example.com?key=${apiKey}`)
-
云端部署时(Vercel / Netlify / Cloudflare Pages)
- 在平台的 Environment Variables 里添加
VITE_API_KEY
- 重新部署项目
- 在平台的 Environment Variables 里添加
安全性
- 风险:构建后,密钥会被写进最终的 JS 文件,别人可以通过浏览器调试查看
- 适用场景:非敏感信息、公开 API、埋点统计等
方案 2:Serverless 函数代理(最安全,推荐用于敏感密钥)
原理
- 前端不直接调用第三方 API
- 前端请求发送到自己的 Serverless API(部署在 Vercel、Netlify 等)
- Serverless API 在服务端读取环境变量里的密钥,调用第三方 API
- 返回结果给前端
这样,密钥永远不会出现在浏览器。
使用示例(Vercel)
-
在 Vercel 项目的 Environment Variables 添加:
DEEPSEEK_API_KEY=sk-xxxxxx
-
创建
/api/deepseek.ts
export default async function handler(req, res) {const response = await fetch('https://api.deepseek.com/v1/chat/completions', {method: 'POST',headers: {'Authorization': `Bearer ${process.env.DEEPSEEK_API_KEY}`,'Content-Type': 'application/json',},body: JSON.stringify(req.body),})const data = await response.json()res.json(data) }
-
前端调用:
const res = await fetch('/api/deepseek', {method: 'POST',body: JSON.stringify({ prompt: 'Hello AI' }), }) const data = await res.json()
安全性
- 优点:密钥只存在服务端环境变量,前端看不到
- 缺点:需要配置 Serverless 函数,稍微复杂
- 适用场景:所有敏感 API(支付、AI、数据库等)
两种方法对比
特性 | 方案 1:环境变量 + 构建注入 | 方案 2:Serverless 代理 |
---|---|---|
密钥是否可见 | 打包后可见 | 不可见 |
配置复杂度 | 低 | 中 |
适用场景 | 非敏感 API | 敏感 API |
安全性 | ★☆☆☆☆ | ★★★★★ |
结论
-
如果密钥不敏感(比如埋点、测试接口),方案 1 就够了
-
如果是敏感 API(AI 调用、支付、数据库),必须用方案 2
“前端直接存储密钥是不安全的,常用两种方法:一种是构建时通过环境变量注入,另一种是通过 Serverless 函数代理 API 请求,确保密钥不暴露给客户端。”