CORS 跨域问题解决方案汇总

CORS 跨域问题解决方案汇总

_

本文总结了在微信 OAuth H5 项目中遇到的 CORS 跨域问题及其多种解决方案。


问题背景

  • 前端域名: https://h5.onefind.club

  • 后端 API: https://api.onefind.club/interface-server/api/queryWeixinOpenIDByCode.json

  • 错误信息:

Access to XMLHttpRequest at 'https://api.onefind.club/...' 
from origin 'https://h5.onefind.club' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

解决方案

方案一:后端添加 CORS 响应头(最佳方案)

后端服务器在响应中添加 CORS 相关的 HTTP 响应头。

适用场景

  • 有后端服务器的修改权限

  • 生产环境推荐方案

  • 需要精细化控制跨域策略

实现方式

Node.js (Express)

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'https://h5.onefind.club');
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  
  // 处理 OPTIONS 预检请求
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  next();
});

Java (Spring Boot)

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("https://h5.onefind.club");
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        config.setAllowCredentials(true);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

Nginx (后端 API 服务器)

location /interface-server/ {
    # 添加 CORS 响应头
    add_header 'Access-Control-Allow-Origin' 'https://h5.onefind.club' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'Content-Type' always;
    
    # 处理 OPTIONS 预检请求
    if ($request_method = 'OPTIONS') {
        return 204;
    }
    
    # 正常代理到后端应用
    proxy_pass http://backend;
}

优缺点

优点

缺点

✅ 从根源解决 CORS 问题

❌ 需要后端配合

✅ 支持复杂跨域场景(带 cookie 等)

❌ 需要修改后端代码或配置

✅ 安全性高,可精确控制

❌ 部署后需要重启服务


方案二:Nginx 反向代理(前端服务器)

在前端服务器的 Nginx 配置中添加反向代理,将 API 请求转发到后端,避免浏览器的同源策略限制。

适用场景

  • 只有前端服务器 Nginx 的修改权限

  • 无法修改后端 API 服务器

  • 快速解决跨域问题

实现方式

Nginx 配置 (h5.onefind.club)

server {
    listen 443 ssl;
    server_name h5.onefind.club;

    # API 反向代理 - 解决 CORS 问题
    location /interface-server/ {
        proxy_pass https://api.onefind.club/interface-server/;
        proxy_set_header Host api.onefind.club;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 前端静态文件
    location / {
        root /var/www/sites/h5.onefind.club/index;
        try_files $uri $uri/ /index.html;
    }
}

前端配置修改

// 修改前
apiBaseUrl: "https://api.onefind.club/",

// 修改后 - 使用相对路径
apiBaseUrl: "/",

请求流程对比

修改前(有 CORS 问题)

浏览器 → https://h5.onefind.club
         ↓ (跨域请求)
         https://api.onefind.club/interface-server/api/xxx.json
         ❌ 被浏览器 CORS 策略阻止

修改后(无 CORS 问题)

浏览器 → https://h5.onefind.club/interface-server/api/xxx.json
         ↓ (同域请求)
         Nginx 反向代理
         ↓
         https://api.onefind.club/interface-server/api/xxx.json
         ✅ 无跨域问题

优缺点

优点

缺点

✅ 无需修改后端

❌ 需要前端服务器配置权限

✅ 实现简单,只需添加 Nginx 配置

❌ 所有请求都经过 Nginx,增加一层

✅ 对前端代码透明

❌ 需要修改前端 API 基础路径


方案三:开发环境代理

仅用于开发环境,生产环境仍需其他方案。

适用场景

  • 本地开发调试

  • 临时解决方案

Vite 配置

// vite.config.ts
export default defineConfig({
  server: {
    proxy: {
      '/interface-server': {
        target: 'https://api.onefind.club',
        changeOrigin: true,
        secure: true,
      }
    }
  }
})

Vue CLI 配置

// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/interface-server': {
        target: 'https://api.onefind.club',
        changeOrigin: true,
        pathRewrite: {
          '^/interface-server': '/interface-server'
        }
      }
    }
  }
}

优缺点

优点

缺点

✅ 开发环境快速解决

❌ 仅限开发环境

✅ 无需修改生产配置

❌ 生产环境仍需其他方案


方案四:使用 WebSocket

WebSocket 协议不受同源策略限制,可以将数据传输改为 WebSocket。

适用场景

  • 需要实时通信

  • 复杂的跨域场景

优缺点

优点

缺点

✅ 不受 CORS 限制

❌ 实现复杂

✅ 支持双向通信

❌ 不适合简单的 API 请求


各方案对比

方案

实现难度

适用场景

推荐指数

后端添加 CORS 响应头

有后端修改权限

⭐⭐⭐⭐⭐

Nginx 反向代理

只有前端服务器权限

⭐⭐⭐⭐

开发环境代理

本地开发

⭐⭐⭐⭐⭐ (开发)

WebSocket

实时通信场景

⭐⭐ (特定场景)


CORS 详解

什么是 CORS

CORS (Cross-Origin Resource Sharing,跨源资源共享) 是一种基于 HTTP 头的机制,允许服务器标示除了它自己以外的其它源(域、协议或端口),浏览器应该允许从这些源加载资源。

同源策略

浏览器默认的同源策略限制:

当前页面 URL

目标 URL

是否同源

https://h5.onefind.club

https://h5.onefind.club/api

✅ 是

https://h5.onefind.club

https://api.onefind.club/api

❌ 否(不同子域)

https://h5.onefind.club

http://h5.onefind.club/api

❌ 否(不同协议)

https://h5.onefind.club:8080

https://h5.onefind.club

❌ 否(不同端口)

CORS 请求类型

1. 简单请求 (Simple Request)

同时满足以下条件:

  • 方法:GET、HEAD、POST

  • 头部:Accept、Accept-Language、Content-Language、Content-Type(仅限 application/x-www-form-urlencodedmultipart/form-datatext/plain

不会触发预检请求。

2. 预检请求 (Preflight Request)

不满足简单请求条件的,浏览器会先发送 OPTIONS 请求:

OPTIONS /interface-server/api/xxx.json HTTP/1.1
Host: api.onefind.club
Origin: https://h5.onefind.club
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

服务器需要响应:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://h5.onefind.club
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400

调试 CORS 问题

1. 浏览器控制台

查看 Console 中的 CORS 错误信息:

Access to XMLHttpRequest has been blocked by CORS policy

2. Network 面板

  • 查看 OPTIONS 预检请求的响应

  • 检查响应头中是否包含 Access-Control-Allow-Origin

3. curl 测试

# 测试是否支持 CORS
curl -I -H "Origin: https://h5.onefind.club" \
  https://api.onefind.club/interface-server/api/queryWeixinOpenIDByCode.json

最佳实践

  1. 生产环境:优先使用后端添加 CORS 响应头

  2. 无后端权限:使用 Nginx 反向代理

  3. 开发环境:使用 devServer 代理

  4. 避免:JSONP、no-cors 模式等不安全方案


参考资料


Vue3 + FastAPI 后台管理系统 2026-01-29
配置路由Vue Router 2026-01-28

评论区