前端暴露API Key被盗刷?Workers代理5分钟保护密钥,每天10万次免费

引言
上个月做了个小工具,调用了 ChatGPT 的 API。为了方便,我直接把 API Key 写在了前端代码里。结果第二天早上醒来,发现账户被盗刷了 300 多块钱。 打开后台一看,一晚上调用了好几千次 API。我当时真的慌了,赶紧把 Key 删了重新生成。但问题是,这个 Key 已经暴露在前端代码里了,就算我改了,下次还会出现同样的问题。 可能你会说,用环境变量不就行了?说实话,我一开始也这么想。后来才发现,Vite 或 Webpack 的环境变量最终还是会被打包到 JS 文件里,用户打开浏览器的 Network 面板就能看到完整的请求,包括你的 API Key。 那怎么办?传统方案是搭个后端服务器做代理,把 API Key 藏在服务端。但这又带来新问题:买服务器要钱(最便宜也得几十块一个月),还得配置环境、处理 SSL 证书、搞定跨域…对个人项目来说实在太重了。 直到我发现了 Cloudflare Workers。5分钟就部署好了一个 API 代理,API Key 存在服务端环境变量里,前端完全接触不到。关键是完全免费,每天有 10 万次请求额度,对个人项目来说绰绰有余。跨域问题也一并解决了。 这篇文章我会手把手教你怎么搭建,代码都是可以直接复制用的。如果你也在为 API Key 安全发愁,这个方案肯定能帮到你。
为什么 API Key 不能放前端
前端代码完全透明
很多人以为用了 .env 文件或者 Vite 的 import.meta.env 就安全了。其实这只是开发时的便利工具,build 之后所有环境变量都会被硬编码到 JS 文件里。 不信你可以试试:打开任何一个前端项目的生产环境,按 F12 打开开发者工具,切到 Network 面板,刷新页面。你会看到所有的 API 请求,包括请求头、请求体、URL 参数,全都暴露出来了。 就算你用了代码混淆、压缩,也只是让代码难读一点。但 API 调用必须要发送真实的 Key,这个是没法混淆的。有人想过加密?问题是加密和解密的代码都在前端,用户一样可以看到。 说白了,前端就是在用户的浏览器里跑,你能做的任何事情,用户都能做。这是无解的。
被盗用的代价有多大
我之前觉得,谁会无聊到扒我的代码偷 API Key 啊?后来才知道,互联网上专门有人干这个。 GitHub 上有自动扫描项目的工具,专门找代码里暴露的 API Key。找到之后有人拿去刷接口,要么是薅羊毛,要么是卖给别人用。OpenAI 的 API 是按 token 计费的,被盗刷一晚上几百块很正常,严重的上千都有。 我在一个开发者论坛看到过讨论,有人做了个 AI 聊天页面,把 Key 放前端了。结果被人扒了之后疯狂调用,一个月账单直接飙到 2000 多美金。虽然后来申诉成功了,但这个过程真的很闹心。 而且不只是 OpenAI,Google Maps API、各种天气 API、翻译 API,只要是按量计费的,都有被盗刷的风险。
传统方案的问题
知道了风险之后,我开始研究怎么解决。网上的方案基本都是:“搭个后端服务器做代理”。 听起来很简单,实际上:
- 成本问题:最便宜的云服务器(阿里云、腾讯云的轻量应用服务器)也要 50-100 块一个月。虽然不算贵,但对于个人小项目来说,这个成本挺肉疼的。
- 配置复杂:要装 Node.js 或者其他运行环境,配置 Nginx 做反向代理,申请 SSL 证书搞 HTTPS,还得处理跨域配置…光是把这些弄明白就要花半天时间。
- 维护成本:服务器要定期更新,要监控运行状态,万一挂了还得重启。小项目真的扛不住这个折腾。 国内大厂的 Serverless 函数(比如阿里云函数计算、腾讯云云函数)确实能省钱,但配置更复杂,冷启动慢,文档也不太友好。我试过几次都没成功。 API 网关听起来很专业,但那都是企业级产品,对个人开发者来说门槛太高了。
Cloudflare Workers 方案优势
完全免费且性能强大
Cloudflare Workers 的免费额度是每天 10 万次请求。对个人项目来说,这个量真的很够用了。我做的那个小工具,一天也就几百次调用,用免费额度绰绰有余。 而且 Cloudflare 在全球有 200 多个数据中心,你的代码会自动部署到这些节点上。用户访问的时候,会自动路由到最近的节点,响应速度特别快。不像传统服务器,你买在哪个地区,其他地区访问就会慢。 还有一个很重要的点:Workers 没有冷启动问题。Serverless 函数(比如 AWS Lambda)如果长时间没请求,下次调用会有几秒的启动延迟。Workers 基本上是毫秒级响应,体验和传统服务器差不多。
部署极其简单
我第一次用 Workers 的时候,从注册账号到部署完成,真的就花了 5 分钟。不夸张。 不需要配置服务器环境,不需要装 Node.js、Nginx 这些,甚至不需要申请 SSL 证书(Workers 自动给你 HTTPS)。你要做的就是:
- 写代码(一个 JS 文件,几十行搞定)
- 运行一条命令:
wrangler publish - 完事了 部署完 Cloudflare 会给你一个域名,类似
your-worker.your-subdomain.workers.dev,可以直接用。如果想用自己的域名也行,在控制台绑定一下就好,不需要额外配置。 对比一下传统方案:买服务器 → 配置环境 → 写代码 → 配置 Nginx → 申请证书 → 部署 → 测试…光是看流程就头大。
天然解决跨域问题
前端调用第三方 API 经常遇到 CORS 错误,比如:Access to fetch at 'xxx' from origin 'yyy' has been blocked by CORS policy。 这是因为浏览器的安全限制,不同域名之间的请求会被拦截。传统方案是让 API 提供方在响应头加 CORS 配置,但第三方 API 你改不了人家的配置啊。 用 Workers 做代理就完美解决了:
- 前端调用的是你自己的 Workers 地址(比如
https://api.yourdomain.com) - Workers 去调用第三方 API
- Workers 在返回响应的时候,加上 CORS 头 对浏览器来说,你就是在调用同源的接口,不存在跨域问题。对第三方 API 来说,调用方是 Workers 的服务器,也不存在跨域问题。 我之前调用高德地图 API 的时候,一直报 CORS 错误。用了 Workers 代理之后,加两行代码就搞定了。
实战:搭建你的第一个 API 代理
好了,说了这么多优点,下面我手把手教你怎么搭建。以代理 OpenAI API 为例,其他 API 的方法都差不多。
第一步:环境准备
1. 注册 Cloudflare 账号 去 cloudflare.com 注册一个账号,免费的就行。注册流程很简单,邮箱验证一下就好。 2. 安装 Wrangler CLI Wrangler 是 Cloudflare 官方的命令行工具,用来创建和部署 Workers。
npm install -g wrangler如果你没装 Node.js,先去 nodejs.org 下载安装。 3. 登录授权
wrangler login运行这个命令会打开浏览器,让你授权。点同意就行,之后命令行工具就能管理你的 Workers 了。
第二步:创建 Worker 项目
wrangler init openai-proxy运行这个命令,会问你几个问题:
- “Would you like to use TypeScript?” → 选 No(除非你熟悉 TS)
- “Would you like to create a new Worker?” → 选 Yes
- “Would you like to install dependencies?” → 选 Yes 完成后会生成一个项目文件夹,结构大概是这样:
openai-proxy/
├── src/
│ └── index.js # 你的代码写这里
├── wrangler.toml # 配置文件
└── package.json第三步:编写代理代码
打开 src/index.js,把里面的默认代码删掉,换成下面这段:
export default {
async fetch(request, env) {
// 只允许 POST 请求
if (request.method !== 'POST') {
return new Response('Method not allowed', { status: 405 });
}
// 从环境变量读取 OpenAI API Key
const apiKey = env.OPENAI_API_KEY;
if (!apiKey) {
return new Response('API Key not configured', { status: 500 });
}
try {
// 获取前端发来的请求体
const body = await request.json();
// 调用真正的 OpenAI API
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`, // 这里用的是服务端的 Key
},
body: JSON.stringify(body),
});
// 获取响应数据
const data = await response.json();
// 返回给前端,并添加 CORS 头
return new Response(JSON.stringify(data), {
status: response.status,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*', // 允许所有域名访问
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': 'Content-Type',
},
});
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
},
};代码很简单:
- 接收前端的 POST 请求
- 从环境变量读取真正的 API Key(这个 Key 前端永远看不到)
- 用这个 Key 去调用 OpenAI API
- 把结果返回给前端,同时加上 CORS 头解决跨域问题
第四步:配置 Secrets(存储 API Key)
这是最关键的一步。API Key 不能写在代码里,要用 Cloudflare 的 Secrets 功能加密存储。 运行这个命令:
wrangler secret put OPENAI_API_KEY回车后会提示你输入 Key 的值。把你的 OpenAI API Key 粘贴进去,回车。 这个 Key 会被加密保存到 Cloudflare 服务器,在控制台里都看不到明文。代码里通过 env.OPENAI_API_KEY 就能读取到。 本地开发怎么办? 在项目根目录创建一个 .dev.vars 文件:
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx这个文件只在本地开发时用,千万别提交到 Git。在 .gitignore 里加一行:
.dev.vars第五步:本地测试
在项目目录下运行:
wrangler dev这会启动一个本地服务器,默认是 http://localhost:8787。你可以用 Postman 或者前端代码测试一下:
fetch('http://localhost:8787', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: 'Hello!' }],
}),
})
.then(res => res.json())
.then(data => console.log(data));如果能正常返回 OpenAI 的响应,说明代理工作正常。
第六步:部署到生产环境
测试没问题后,一条命令部署:
wrangler publish几秒钟就好了。部署完 Cloudflare 会给你一个地址,类似:
https://openai-proxy.your-subdomain.workers.dev把前端代码里的 API 地址改成这个,就大功告成了!API Key 完全不会暴露到前端。 如果想用自己的域名,在 Cloudflare 控制台的 Workers 页面,点你的 Worker → Settings → Triggers → Add Custom Domain,输入你的域名(比如 api.yourdomain.com),然后按提示配置 DNS 就行。
进阶技巧和最佳实践
上面的代码可以跑起来了,但还有些可以优化的地方。下面我分享几个进阶技巧。
防止你的代理被滥用
现在你的 Worker 是公开的,任何人知道地址都能调用。如果有人恶意刷接口,你的免费额度可能很快用完,严重的话还会产生费用。 简单的 Token 验证 可以加一个简单的验证机制:
export default {
async fetch(request, env) {
// 验证请求头里的 token
const token = request.headers.get('X-API-Token');
if (token !== env.MY_SECRET_TOKEN) {
return new Response('Unauthorized', { status: 401 });
}
// ... 后面的代理逻辑
},
};然后用 wrangler secret put MY_SECRET_TOKEN 设置一个密钥。前端调用的时候带上这个 token:
fetch('https://your-worker.workers.dev', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Token': 'your-secret-token', // 这个 token 也可以放在前端环境变量里
},
body: JSON.stringify(data),
});虽然这个 token 前端还是能看到,但至少增加了一层门槛。你可以定期更换 token,或者针对不同用户分配不同 token。 IP 白名单 如果你的应用只在特定域名下使用,可以限制来源:
const allowedOrigins = ['https://yourdomain.com', 'http://localhost:3000'];
const origin = request.headers.get('Origin');
if (!allowedOrigins.includes(origin)) {
return new Response('Forbidden', { status: 403 });
}支持多个 API
如果你要代理多个不同的 API,可以通过路径区分:
export default {
async fetch(request, env) {
const url = new URL(request.url);
// 根据路径转发到不同的 API
if (url.pathname.startsWith('/openai')) {
return proxyOpenAI(request, env);
} else if (url.pathname.startsWith('/maps')) {
return proxyMaps(request, env);
} else {
return new Response('Not found', { status: 404 });
}
},
};
async function proxyOpenAI(request, env) {
// OpenAI 代理逻辑
}
async function proxyMaps(request, env) {
// 地图 API 代理逻辑
}这样一个 Worker 就能处理多个 API,很方便。
处理 OPTIONS 请求(完整的 CORS 支持)
前面的代码只处理了 POST 请求。但浏览器在发送跨域请求之前,会先发一个 OPTIONS 预检请求。完整的 CORS 处理应该这样:
export default {
async fetch(request, env) {
// 处理 CORS 预检请求
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, X-API-Token',
'Access-Control-Max-Age': '86400',
},
});
}
// ... 正常的请求处理
},
};监控和调试
Cloudflare 控制台可以查看 Worker 的运行情况:
- 请求次数
- 错误率
- 响应时间 如果想实时查看日志,可以用
wrangler tail命令:
wrangler tail这会输出所有请求的日志,方便调试。在代码里用 console.log() 输出的内容也会显示出来。
常见问题解答
免费额度用完了怎么办? 每天 10 万次请求对个人项目来说真的很够用了。我自己的项目用了几个月,从来没超过免费额度。 如果真的不够,Workers 的付费版也不贵,5 美元一个月可以用 1000 万次请求。相比买服务器,这个价格已经很良心了。 Workers 稳定吗?会不会突然挂掉? Cloudflare 是全球最大的 CDN 提供商之一,基础设施非常可靠。我用了大半年,没遇到过服务不可用的情况。 官方有 99.99% 的 SLA 保证,出问题的概率比你自己搭服务器小多了。 可以用自己的域名吗? 可以的。在 Cloudflare 控制台绑定自定义域名,然后配置一下 DNS 就行。整个过程 5 分钟搞定,不需要额外配置证书(自动 HTTPS)。 国内访问速度怎么样? Cloudflare 在国内有节点,速度还可以。我测试过,响应时间一般在 100-300ms,比直接调用国外的 API 快很多。 但确实不如专门针对国内优化的服务。如果对速度要求特别高,可以考虑用国内的 Serverless 平台(比如阿里云函数计算)。不过那个配置更复杂。 除了 JavaScript,支持其他语言吗? Workers 目前主要支持 JavaScript 和 TypeScript。如果你习惯用其他语言,可以考虑用编译到 WebAssembly 的方式,但那个门槛比较高。 对于 API 代理这种简单场景,JavaScript 完全够用了。 这样做真的安全吗? 只要你不在响应里把 API Key 返回给前端,就是安全的。Secrets 是加密存储的,在控制台都看不到明文。 当然,你还是要做好访问控制,避免代理被滥用。上面提到的 token 验证、IP 白名单都可以用上。
结论
API Key 泄露这个问题困扰了我挺久。一开始我以为没什么好办法,要么忍受风险,要么花钱买服务器。 直到发现 Cloudflare Workers,才意识到原来可以这么简单。5 分钟部署,完全免费,API Key 安全存储,跨域问题一并解决,这些优势加起来,Workers 几乎是个人项目的完美方案。 如果你也在做需要调用第三方 API 的项目,强烈建议试试这个方法。真的不难,跟着上面的步骤操作,半小时肯定能搞定。 代码我都写得很详细了,直接复制改改就能用。有问题可以查 Cloudflare 官方文档,或者在评论区留言,我看到会回复。 最后提醒一句:部署完记得做好访问控制,别让你的代理被滥用了。加个 token 验证,或者限制一下来源域名,都是很简单但有效的办法。 现在就去注册个 Cloudflare 账号试试吧!
发布于: 2025年12月1日 · 修改于: 2025年12月4日


