跨域常用解决方案

先搞清楚一个事实:浏览器根本不关心你代码写得对不对

跨域报错最让人崩溃的地方在于:请求发出去了,服务端也响应了,数据也返回了,但浏览器就是不给你。

这不是你的代码有问题,也不是后端接口挂了。浏览器的同源策略在 Fetch 或 XHR 的响应阶段 介入,检查响应头里有没有 Access-Control-Allow-Origin。如果这个头缺失或不匹配,响应体直接丢弃,前端拿到一个空壳。

所以跨域的本质是:服务端必须通过响应头告诉浏览器"我允许这个源访问" 。后端不改,前端怎么折腾都没用。

下面按实际开发场景说人话。

CORS:唯一正确的生产级方案

CORS 不是"绕过"跨域,它是 W3C 标准定义的跨域正式通道 。服务端设置响应头,浏览器验证放行。

关键响应头只有几个:

http

yaml 复制代码
Access-Control-Allow-Origin: https://your-frontend.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true

最容易踩的坑在 Preflight(预检请求) 。当你的请求满足以下任一条件时,浏览器会先发一个 OPTIONS 探路请求:

  • 方法不是 GET/HEAD/POST
  • Content-Type 是 application/json(而不是 text/plain)
  • 带了自定义请求头(比如 Authorization)

这个 OPTIONS 请求不携带你的业务参数,服务端必须返回 204 或 200,并附带上述 CORS 响应头。如果后端只处理了 POST 没处理 OPTIONS,预检就挂了,正式请求根本发不出去。

带 Cookie 的场景更严格 :Access-Control-Allow-Origin 不能是 *,必须写明确的前端域名,同时 Access-Control-Allow-Credentials: true。

开发阶段的代理:不是解决跨域,是消灭跨域

CORS 需要后端配合,但开发时后端经常还没部署、或懒得给你配 CORS。代理的本质是:让浏览器以为请求发给了同源的服务,再由开发服务器转发到真正的后端。

Vite 代理(当前最主流)

javascript

javascript 复制代码
// vite.config.js
export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3001',
        changeOrigin: true,
        rewrite: path => path.replace(/^/api/, '')
      }
    }
  }
}

前端代码里写 fetch('/api/users'),Vite Dev Server 收到后转发到 localhost:3001/users。浏览器全程只和 localhost:5173 打交道,同源,无跨域。

Nginx 反向代理(生产环境标准答案)

开发用 Vite,生产用 Nginx,这是目前最常见的前后端分离部署方式:

nginx

bash 复制代码
location /api/ {
    proxy_pass http://backend-service:3001;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

前端静态文件和 /api 请求都在同一个 Nginx 域名下,浏览器视角全是同源。

代理方案的真正价值:不仅消灭了跨域,还隐藏了后端真实地址,顺便解决了 HTTPS 混合内容问题。

命令行禁用 Web 安全:能用,但要知道自己在干什么

有些场景下,你就是不想动后端,也不想配代理。比如临时调一个第三方 API,或者本地调试一个别人的线上页面。

Chrome 的 --disable-web-security 可以直接关掉同源策略。必须配合独立的用户数据目录,否则会和你的日常浏览器配置冲突:

bash

python 复制代码
# macOS
open -n -a "Google Chrome" --args --disable-web-security --user-data-dir=/tmp/chrome_dev

# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir=C:\ChromeDevUserData

启动后地址栏下方会出现黄色警告条"你使用的是不受支持的命令标记",说明配置生效了。

这件事的边界很清楚 :只在你自己的机器上,只用于调试。不要把它当成开发流程的一部分,更不要教给团队里不了解原理的人。--user-data-dir 的意义是隔离,别用你的主浏览器配置跑这个模式。

不该再用的方案

JSONP 可以直接划掉了。 它只能发 GET 请求,没有错误处理,有 XSS 风险,唯一的历史价值是让你理解 <script> 标签不受同源限制这件事。2026 年没有任何理由在新项目里用 JSONP。

document.domain 也已经废弃。 之前用于同一主域下子域间通信,现在浏览器逐步移除支持,不要再写进技术方案里。

WebSocket 本身不受同源策略约束 ,但服务端必须自己校验 Origin 头,否则等于把安全责任从浏览器转移给了开发者。如果你用 WebSocket 做实时通信,跨域不是问题,鉴权才是。

选型建议

一张表说清楚:

场景 方案
前后端联调,后端已部署 让后端配 CORS
后端还没好 / 不想打扰后端 Vite/Webpack 代理
生产环境前后端分离 Nginx 反向代理
临时调第三方 API,只想快速验证 Chrome 禁用安全模式
微前端 / iframe 通信 postMessage

核心判断逻辑:能控制后端就上 CORS,不能控制就用代理,都不想动就开一个隔离的调试浏览器。别把临时方案塞进生产代码里。

相关推荐
传人once1 小时前
页面中心圆圈放大效果如何写
开发语言·javascript·ecmascript
用户033307413952 小时前
TypeScript using 与 AsyncDisposableStack:在真实服务端代码中协调多资源清理
前端
daisychey2 小时前
用 Playwright 做多平台内容分发,我踩过的 8 个坑
前端
IT_陈寒3 小时前
为什么你应该学习JavaScript?
前端·人工智能·后端
大龄秃头程序员3 小时前
iOS冷启动监控Demo
前端
光影少年3 小时前
为什么 JavaScript 中 0.1 + 0.2 !== 0.3,如何让其相等?
前端·javascript·算法
掘金酱4 小时前
[稀土掘金 × 火山引擎] AI用量周榜冲刺赛|获奖名单公示
前端·人工智能·后端
泡泡oO4 小时前
“如果你还在用Superpowers,那我不要和你说话”
前端·后端·全栈
维克兜率天4 小时前
趋势过滤:避免被“假突破“反复打脸
前端
8年区块链老兵5 小时前
一篇文章教会你:用区块高度读懂比特币链上的每一笔交易
前端