详细分析CORS 工作原理

🎯 CORS 是什么?

CORS 是一种安全机制,允许网页从不同的域(域名、协议、端口)请求资源。由于您的前端和后端部署在不同的域名上:

  • 前端:https://your-pages.pages.dev (Cloudflare Pages)
  • 后端:https://your-worker.workers.dev (Cloudflare Workers)

浏览器会阻止这种跨域请求,除非后端明确允许。

🔍 代码逐行分析

typescript 复制代码
export function handleCors(request: Request): Response | null {
  // 检查是否是 OPTIONS 请求(预检请求)
  if (request.method === 'OPTIONS') {
    // 如果是预检请求,返回一个空的响应和CORS头
    return new Response(null, {
      headers: {
        // 允许指定的前端域名进行跨域访问
        'Access-Control-Allow-Origin': 'https://your-pages.pages.dev',
        
        // 允许的HTTP方法
        'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
        
        // 允许的请求头
        'Access-Control-Allow-Headers': 'Content-Type, Authorization',
      },
    });
  }
  // 如果不是OPTIONS请求,返回null,让主流程继续处理
  return null;
}

🌐 CORS 工作原理

1. 预检请求 (OPTIONS)

当浏览器发送跨域请求时,会先发送一个 OPTIONS 请求来询问服务器是否允许实际请求。

示例流程:

复制代码
前端 (https://your-pages.pages.dev)
  → 发送 OPTIONS 预检请求到后端
  ← 后端返回 CORS 头
  → 浏览器检查通过后发送实际请求 (GET/POST)
  ← 后端返回实际数据

2. 实际请求

预检通过后,浏览器才会发送真正的请求(GET、POST等)。

🛠️ 改进建议

1. 动态允许域名(推荐)

typescript 复制代码
export function handleCors(request: Request): Response | null {
  // 允许的前端域名列表
  const allowedOrigins = [
    'https://your-pages.pages.dev',      // 生产环境
    'http://localhost:3000',             // 本地开发
    'http://localhost:5173'              // Vite 开发服务器
  ];
  
  const origin = request.headers.get('Origin');
  const allowedOrigin = allowedOrigins.includes(origin || '') ? origin : allowedOrigins[0];

  if (request.method === 'OPTIONS') {
    return new Response(null, {
      headers: {
        'Access-Control-Allow-Origin': allowedOrigin || '*',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Requested-With',
        'Access-Control-Allow-Credentials': 'true',
        'Access-Control-Max-Age': '86400', // 24小时缓存
      },
    });
  }
  return null;
}

2. 在实际响应中也添加CORS头

typescript 复制代码
// 在您的各个handler中,也需要添加CORS头
export function successResponse(data: any, message?: string): Response {
  return new Response(JSON.stringify({ success: true, data, message }), {
    headers: {
      'Content-Type': 'application/json',
      'Access-Control-Allow-Origin': 'https://your-pages.pages.dev',
      'Access-Control-Allow-Credentials': 'true',
    },
  });
}

export function errorResponse(message: string, status: number = 500): Response {
  return new Response(JSON.stringify({ success: false, error: message }), {
    status,
    headers: {
      'Content-Type': 'application/json',
      'Access-Control-Allow-Origin': 'https://your-pages.pages.dev',
      'Access-Control-Allow-Credentials': 'true',
    },
  });
}

3. 完整的使用示例

typescript 复制代码
// src/index.ts
import { handleCors, successResponse } from './utils/response';

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    // 1. 首先处理CORS预检请求
    const corsResponse = handleCors(request);
    if (corsResponse) return corsResponse;

    // 2. 处理实际请求
    const url = new URL(request.url);
    
    if (url.pathname === '/api/test') {
      // 3. 在实际响应中也添加CORS头
      return successResponse({ message: 'Hello World' });
    }

    return new Response('Not found', { status: 404 });
  }
};

🔧 常见CORS头说明

头字段 说明 示例
Access-Control-Allow-Origin 允许的源 https://your-site.com
Access-Control-Allow-Methods 允许的HTTP方法 GET, POST, OPTIONS
Access-Control-Allow-Headers 允许的请求头 Content-Type, Authorization
Access-Control-Allow-Credentials 是否允许发送cookie true
Access-Control-Max-Age 预检请求缓存时间 86400 (秒)

💡 重要提示

  1. ** credentials **:如果前端需要发送cookie,需要设置 Access-Control-Allow-Credentials: true,并且 Access-Control-Allow-Origin 不能是通配符 *

  2. ** 生产环境配置 **:记得将 https://your-pages.pages.dev 替换为您实际的前端域名

  3. ** 本地开发 **:建议允许本地开发服务器的域名,方便调试

这段代码是确保您的前后端分离架构能够正常工作的关键!🚀

相关推荐
番茄源码20 天前
【实战项目教程】springboot3 vue3非物质文化遗产系统
java·spring boot·前后端分离
炸裂狸花猫25 天前
开源域名代理与流量限制方案 - Cloudflare + Ingress + 自签名证书
运维·云原生·容器·kubernetes·cloudflare·waf·免费域名证书
IT教程资源D1 个月前
[N_160]基于springboot,vue校园论坛系统
mysql·vue·前后端分离·springboot校园论坛·校园论坛交流系统
海棠AI实验室1 个月前
第 6 篇:访问控制与零信任策略
mac·cloudflare
IT教程资源1 个月前
N-159基于springboot,vue,AI协同过滤算法旅游推荐系统
mysql·vue·前后端分离·springboot旅游推荐·协同过滤算法旅游推荐·ai旅游推荐
海棠AI实验室1 个月前
第 5 篇:Cloudflare Tunnel 多服务路由模板
cloudflare
zhengxianyi5151 个月前
只需3句让Vue3 打包部署后通过修改配置文件修改全局变量——实时生效
vue.js·前后端分离·数据大屏·ruoyi-vue-pro优化
zhengxianyi5151 个月前
Vue2 打包部署后通过修改配置文件修改全局变量——实时生效
前端·vue.js·前后端分离·数据大屏·ruoyi-vue-pro
zhengxianyi5151 个月前
vite build 发布到nginx二级目录——将yudao-ui-go-view打包、部署到big目录下
vue.js·nginx·vite·前后端分离·打包·ruoyi-vue-pro优化·部署运维
zhengxianyi5151 个月前
ruoyi-vue-pro本地环境搭建(超级详细,带异常处理)
前端·vue.js·前后端分离·ruoyi-vue-pro