当前位置: 首页 > article >正文

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

第一部分:问题背景

在这里插入图片描述

1.1 错误现象复现

// 浏览器控制台报错示例
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 为例)

// 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 是后端服务器?
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)绕过同源策略限制。

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;
  }
}

附录
5. 完整 Worker 代理代码示例
6. CORS 调试工具推荐
7. Cloudflare Worker 官方文档


http://www.kler.cn/a/518257.html

相关文章:

  • STM32-时钟树
  • 代码随想录——二叉树(二)
  • 为什么在编程中cast有强制类型转换的意思?
  • 笔灵ai写作技术浅析(一)
  • 每日一题 427. 建立四叉树
  • Avalonia+ReactiveUI跨平台路由:打造丝滑UI交互的奇幻冒险
  • C语言数据结构:链表、栈与队列、排序算法与查找算法深度解析
  • 【C++高并发服务器WebServer】-1:Linux中父子进程fork创建及关系、GDB多进程调试
  • Redis(5,jedis和spring)
  • QModbusTCPClient 服务器断开引起的程序崩溃
  • ChirpIoT技术的优势以及局限性
  • Spring Boot - 数据库集成03 - 集成Mybatis
  • SSM框架探秘:Spring 整合 Mybatis 框架
  • Linux(Centos 7.6)命令详解:wc
  • linux查看上次开机时间
  • Effective C++ 规则46: 需要类型转换时,请为模板定义非成员函数
  • LVGL+FreeRTOS实战项目:智能健康助手(xgzp6847a篇)
  • 【算法工程】VS Code问题解决:Failed to parse remote port from server output
  • Java多线程的面试面试题及答案解析
  • Golang之Context详解
  • 【pytorch 】miniconda python3.11 环境安装pytorch
  • 无公网IP 外网访问媒体服务器 Emby
  • GS论文阅读--GeoTexDensifier
  • 如何实现分页相关功能
  • 比简单工厂更好的 - 工厂方法模式(Factory Method Pattern)
  • Lambda 表达式