Cloudflare通过代理服务器绕过 CORS 限制:原理、实现场景解析

第一部分:问题背景

1.1 错误现象复现

javascript 复制代码
// 浏览器控制台报错示例
Access to fetch at 'https://chat.qwenlm.ai/api/v1/files/' from origin 'https://ocr.doublefenzhuan.me' 
has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

1.2 CORS 机制的核心原理

  • 同源策略 (Same-Origin Policy):浏览器的安全沙箱规则。
  • 预检请求 (Preflight Request)OPTIONS 方法的作用与触发条件。
  • 服务端责任Access-Control-Allow-Origin 等响应头的重要性。

1.3 逆向工程场景的特殊性

  • 无服务器控制权:无法修改目标服务器的 CORS 配置。
  • 突发性策略变更:目标服务器可能动态调整安全规则(如案例中的突然限制)。

第二部分:代理方案的技术实现

2.1 整体架构图

复制代码
[浏览器] --> [同域代理接口 /proxy/upload] --> [目标服务器 chat.qwenlm.ai]

2.2 代码实现详解(以 Cloudflare Worker 为例)

javascript 复制代码
// Worker 路由配置
addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  switch(url.pathname) {
    case '/proxy/upload':
      if (event.request.method === 'POST') {
        return event.respondWith(handleProxyUpload(event.request));
      }
      break;
    // ...其他路由...
  }
});

// 代理请求处理函数
async function handleProxyUpload(request) {
  try {
    // 1. 提取客户端请求内容
    const formData = await request.formData();
    const token = request.headers.get('Authorization')?.replace('Bearer ', '');
    
    // 2. 转发到目标服务器
    const targetResponse = await fetch('https://chat.qwenlm.ai/api/v1/files/', {
      method: 'POST',
      headers: {
        'accept': 'application/json',
        'authorization': `Bearer ${token}`,
      },
      body: formData,
    });
    
    // 3. 返回处理后的响应
    const data = await targetResponse.json();
    return new Response(JSON.stringify(data), {
      headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
      },
    });
  } catch (error) {
    // ...错误处理...
  }
}

2.3 关键代码解析

代码片段 作用说明
case '/proxy/upload' 定义代理路由入口,匹配特定路径的请求
await request.formData() 提取客户端提交的表单数据(含文件上传)
fetch('https://chat.qwenlm.ai') 服务器端发起跨域请求,不受浏览器策略限制
Access-Control-Allow-Origin: * 确保浏览器接受代理返回的响应

第三部分:技术原理深度解析

3.1 为什么代理方案有效?

  • 同源策略的规避 :浏览器只感知到与页面同域的 /proxy/upload 请求。
  • 服务端特权:服务器间通信不受 CORS 限制(Node.js/Python/Worker 等)。
  • 请求头传递 :代理可透传/修改敏感头信息(如 Authorization)。

3.2 与传统方案的对比

方案 优点 缺点 适用场景
修改服务器 CORS 配置 原生支持、性能最佳 需要目标服务器控制权 自有 API 服务
代理方案 无需目标服务器配合 增加中间层、略影响性能 第三方 API/逆向工程
JSONP 兼容老旧浏览器 仅支持 GET、存在安全风险 历史遗留系统
no-cors 模式 快速实现 无法读取完整响应 简单请求且无需响应内容

问题

https://ocr.doublefenzhuan.me/proxy/upload 为什么加了proxy/upload就变成了后端服务器呢?

  1. 关于「后端服务器」的定义
    前端和后端的本质区别在于代码执行的位置:
  • 前端:运行在用户浏览器中的代码(HTML/CSS/JavaScript)。
  • 后端:运行在服务器上的代码(如 Node.js、Python、Java 等)。

URL 路径(如 /proxy/upload)本身不决定前后端,而是看该路径的请求由谁处理:

  • 如果请求由浏览器直接处理(如静态文件请求),属于前端。
  • 如果请求由服务器端代码处理(如动态接口),属于后端。
  1. 为什么 /proxy/upload 是后端服务器?
js 复制代码
case '/proxy/upload':
  if (request.method === 'POST') {
    return handleProxyUpload(request); // 由服务器端代码处理
  }
  break;

路径 /proxy/upload 只是一个路由标识:

当客户端访问 https://ocr.doublefenzhuan.me/proxy/upload 时,请求会被 Worker 脚本捕获。

Worker 脚本根据路由规则(case '/proxy/upload')调用 handleProxyUpload 函数。
handleProxyUpload 是服务器端代码(运行在 Cloudflare Worker 的服务器环境中),因此这个路径对应的逻辑属于后端。

  1. 为什么说「服务器之间没有跨域问题」?
  • CORS 是浏览器强制的安全策略,只影响浏览器发起的请求。
  • 服务器之间的 HTTP 请求(如 Worker → chat.qwenlm.ai)不受 CORS 限制,因为:
    • 服务器没有「同源策略」的概念。
    • 服务器可以自由向任何域名发起请求(除非目标服务器主动封禁)。

4.前端直接发起跨域请求的代码

创建 FormData 对象:前端通过 FormData 对象将文件数据包装成表单格式。 发起跨域请求:使用 fetch 直接向目标服务器 (https://chat.qwenlm.ai/api/v1/files/) 发起 POST 请求。 添加Authorization 头:将用户的认证令牌添加到请求头中。 处理响应:如果请求成功,解析并返回响应数据;如果失败,抛出错误。因为目标服务器不支持 CORS,前端需要通过代理服务器(或 Worker)绕过同源策略限制。

js 复制代码
async function uploadFile(file, token) {
  try {
    // 创建 FormData 对象
    const formData = new FormData();
    formData.append('file', file); // 添加文件

    // 发起 POST 请求
    const response = await fetch('https://chat.qwenlm.ai/api/v1/files/', {
      method: 'POST',
      headers: {
        'accept': 'application/json',
        'authorization': `Bearer ${token}`, // 添加 Authorization 头
      },
      body: formData, // 发送 FormData
    });

    // 处理响应
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Upload failed:', error);
    throw error;
  }
}

附录

  1. 完整 Worker 代理代码示例

  2. CORS 调试工具推荐

  3. Cloudflare Worker 官方文档

相关推荐
用户962377954486 小时前
DVWA 靶场实验报告 (High Level)
安全
炫饭第一名6 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
进击的尘埃8 小时前
Vue3 响应式原理:从 Proxy 到依赖收集,手撸一个迷你 reactivity
javascript
None3218 小时前
【NestJs】基于Redlock装饰器分布式锁设计与实现
后端·node.js
willow8 小时前
JavaScript数据类型整理1
javascript
LeeYaMaster8 小时前
20个例子掌握RxJS——第十一章实现 WebSocket 消息节流
javascript·angular.js
UIUV9 小时前
RAG技术学习笔记(含实操解析)
javascript·langchain·llm
数据智能老司机9 小时前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机9 小时前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
颜酱10 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法