今天花了一整天时间,用 Cloudflare 的免费服务给三个网站(小宝游戏站、小宝科技站、小宝命理站)做了一次全面升级。从 API 密钥安全到评论系统,全程零成本,体验却提升了一大截。
问题的起因
事情是这样的:三个网站都接入了智谱 AI 的对话功能,但 API Key 直接写在前端 HTML 里。虽然加了域名限制,但这种做法总归不够安全。万一有人抓包或者查看源代码,Key 就暴露了。
另外,网站一直没有评论功能,想和访客互动也没办法。市面上的评论系统要么需要服务器,要么要绑银行卡,对我这种纯静态站点来说都不太合适。
解决方案
最终选择了 Cloudflare 全家桶方案:
- Cloudflare Workers:部署 API 代理和评论系统后端
- Cloudflare D1:存储评论数据(免费 5GB)
- Cloudflare Pages:托管静态网站(已在用)
这套方案的优点是:
- 完全免费(在合理用量内)
- 无需服务器和数据库
- 不需要绑定银行卡
- 全球 CDN 加速
- 配置简单,维护成本低
第一步:保护 API 密钥
创建 Worker 代理
在 Cloudflare Dashboard 创建了一个名为 ai-proxy 的 Worker,代码很简单:
export default {
async fetch(request, env) {
// 处理 CORS 预检请求
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type'
}
});
}
// 转发请求到智谱 AI
const response = await fetch('https://open.bigmodel.cn/api/paas/v4/chat/completions', {
method: request.method,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${env.API_KEY}` // 从环境变量读取
},
body: request.body
});
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
});
}
}
关键点是把 API Key 存在 Worker 的环境变量里,前端只需要调用 Worker 的 URL:https://ai-proxy.dygnjdtdq9.workers.dev
修改前端代码
三个网站的 AI 页面都做了相同的修改,把原来的配置:
const API_KEY = 'xxx'; // ❌ 不安全
const BASE_URL = 'https://open.bigmodel.cn/api/paas/v4';
改成:
const BASE_URL = 'https://ai-proxy.dygnjdtdq9.workers.dev'; // ✅ 安全
这样前端代码里就完全看不到 API Key 了,安全性大幅提升。
第二步:优化 404 页面
趁着折腾的劲头,给三个网站都做了定制化的 404 页面。每个站点都有自己的风格:
- 游戏站:🎮 "游戏关卡未找到,要不要回主页重新开始?"
- 科技站:💻 "404 - 页面未找到,可能是链接失效了"
- 命理站:☯️ "缘分未到,此页面暂时无法访问"
同时添加了 _redirects 文件配置路由:
/* /404.html 404
还有 _headers 文件增强安全性:
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Cloudflare Pages 会自动识别这些文件,无需额外配置。
第三步:搭建评论系统
这是今天最大的工程。一开始考虑过 Waline、Twikoo、Giscus 等方案,但要么需要服务器,要么要绑银行卡。最后决定用 Cloudflare D1 + Workers 自己搭一个。
创建 D1 数据库
在 Cloudflare Dashboard 创建数据库 comment-db,然后执行 SQL 初始化表结构:
CREATE TABLE IF NOT EXISTS Comment (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nick TEXT NOT NULL,
mail TEXT,
link TEXT,
comment TEXT NOT NULL,
url TEXT NOT NULL,
createdAt TEXT DEFAULT (datetime('now')),
updatedAt TEXT DEFAULT (datetime('now'))
);
部署 Worker API
创建 worker-api Worker,实现评论的增删改查:
export default {
async fetch(request, env) {
const url = new URL(request.url);
// 获取评论列表
if (request.method === 'GET' && url.pathname === '/api/comment') {
const pageUrl = url.searchParams.get('url');
const { results } = await env.DB.prepare(
'SELECT * FROM Comment WHERE url = ? ORDER BY createdAt DESC'
).bind(pageUrl).all();
return new Response(JSON.stringify({ data: results }), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
});
}
// 提交评论
if (request.method === 'POST' && url.pathname === '/api/comment') {
const data = await request.json();
await env.DB.prepare(
'INSERT INTO Comment (nick, mail, link, comment, url) VALUES (?, ?, ?, ?, ?)'
).bind(data.nick, data.mail, data.link, data.comment, data.url).run();
return new Response(JSON.stringify({ success: true }), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
});
}
return new Response('Waline API Server - Powered by Cloudflare D1');
}
}
在 Worker 设置中绑定 D1 数据库,变量名设为 DB。
前端实现
一开始尝试用 Waline 的客户端库,但发现 API 格式不兼容,调试了很久都不行。最后决定用纯原生 JavaScript 实现,反而更简单:
// 加载评论
async function loadComments() {
const response = await fetch(
`${API_URL}/api/comment?url=${encodeURIComponent(location.pathname)}`
);
const data = await response.json();
renderComments(data.data);
}
// 提交评论
async function submitComment(formData) {
const response = await fetch(`${API_URL}/api/comment`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nick: formData.get('nick'),
mail: formData.get('mail'),
link: formData.get('link'),
comment: formData.get('comment'),
url: location.pathname
})
});
return response.json();
}
创建了测试页面 comment-test-native.html,功能包括:
- 提交评论(昵称、邮箱、网站、内容)
- 显示评论列表
- 时间格式化(刚刚、X分钟前、X小时前)
- 空状态提示
测试成功后,第一条评论顺利提交,数据库也正常存储了。
成果展示
API 安全
- ✅ API Key 完全隐藏,前端无法获取
- ✅ 三个网站的 AI 功能正常工作
- ✅ 可以随时在 Worker 中更换 Key 或服务商
404 页面
- ✅ 三个网站都有了定制化的 404 页面
- ✅ 添加了安全响应头
- ✅ 用户体验更友好
评论系统
- ✅ 纯原生实现,无第三方依赖
- ✅ 数据存储在 Cloudflare D1
- ✅ 支持基本的评论功能
- ✅ 响应速度快,全球可用
一些思考
为什么选择 Cloudflare?
主要是因为:
- 免费额度够用(Workers 每天 10 万次请求,D1 5GB 存储)
- 不需要绑定银行卡
- 全球 CDN,访问速度快
- 配置简单,文档清晰
- 和 Cloudflare Pages 无缝集成
遇到的坑
- Waline 客户端兼容性:官方客户端期望的 API 格式和我的实现不一致,最后放弃了第三方库
- CORS 配置:一开始忘了处理 OPTIONS 预检请求,导致跨域失败
- D1 绑定:Worker 绑定数据库时变量名必须和代码中的
env.DB一致
后续计划
- 给评论系统添加回复功能
- 实现评论审核机制
- 添加邮件通知
- 考虑接入 Akismet 反垃圾评论
- 把评论系统集成到文章页面
写在最后
这次折腾最大的收获是验证了 Cloudflare 全家桶的可行性。对于个人开发者来说,不需要服务器、不需要数据库、不需要绑卡,就能搭建出功能完整的网站基础设施,这在以前是不可想象的。
虽然花了一整天时间,但看到评论系统成功运行的那一刻,还是很有成就感的。代码都是自己写的,数据也在自己掌控之中,这种感觉比用现成的服务要踏实得多。
如果你也在用 Cloudflare Pages 托管静态网站,不妨试试这套方案。成本为零,体验却不打折扣。
加载评论中...