变量名必须是MY_R2_BUCKET
x// ===================== 固定配置 =====================const R2_BINDING = "MY_R2_BUCKET";// 防盗链:允许通过 Referer 直接加载的域名const ALLOWED_DOMAINS = ["baidu.com"];// ====================================================
export default { async fetch(request, env, ctx) { const url = new URL(request.url); const path = url.pathname; const referer = request.headers.get("Referer") || "";
// ---------- 处理预检请求(CORS) ---------- if (request.method === "OPTIONS") { return new Response(null, { status: 204, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, OPTIONS", "Access-Control-Allow-Headers": "Content-Type", "Access-Control-Max-Age": "86400", }, }); }
// ---------- 图片代理(防盗链) ---------- if (path.includes("drawingbed") || path.includes(".png") || path.includes(".jpg")) { const token = url.searchParams.get("token") || ""; const ACCESS_TOKEN = env.ACCESS_TOKEN || "";
let isAllowed = false;
// 1. Referer 域名匹配 for (const domain of ALLOWED_DOMAINS) { if (referer.includes(domain)) { isAllowed = true; break; } }
// 2. Token 验证 if (!isAllowed && token === ACCESS_TOKEN) { isAllowed = true; }
if (!isAllowed) { return new Response("禁止访问", { status: 403 }); }
const imgPath = decodeURIComponent(path.slice(1)).normalize('NFC'); const obj = await env[R2_BINDING].get(imgPath); if (!obj) return new Response("图片不存在", { status: 404 });
const headers = new Headers(); obj.writeHttpMetadata(headers); headers.set("Cache-Control", "public, max-age=86400"); headers.set("Access-Control-Allow-Origin", "*"); return new Response(obj.body, { headers }); }
// ---------- 其他请求 ---------- return new Response("请求无效", { status: 400 }); },};ACCESS_TOKEN: 用于验证图片
假如我的worker域名为:https://1795857.xyz,某张图片的存储桶路径为:bucket/1.jpg,ACCESS_TOKEN: my_ACCESS_TOKEN
ALLOWED_DOMAINS设置的referer站点的引用:worker域名 + 文件路径,即https://1795857.xyz/bucket/1.jpghttps://1795857.xyz/bucket/1.jpg?token=my_ACCESS_TOKENBy @Jrafina 2026-04-27 本博文内容为原创作品,未经允许不得转载。如需转载,请注明原作者及出处。