跨域常用解决方案

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

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

这不是你的代码有问题,也不是后端接口挂了。浏览器的同源策略在 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,不能控制就用代理,都不想动就开一个隔离的调试浏览器。别把临时方案塞进生产代码里。

相关推荐
程序员大阳5 小时前
副队长JavaScript教程(49)-主动抛出异常与错误类型
javascript·异常处理·error·throw·错误类型
hhhjhl5 小时前
Protobuf.js 跨端三方库仓颉适配全流程
javascript·网络·udp
康小汪5 小时前
AI 写 Vue 总写成同一个味道:给它装 Skills,装的不是知识是边界
前端·vue.js·人工智能·ai编程·最佳实践
智能运维指南6 小时前
研制过程“两张皮“怎么破:研制一体化支撑平台的定位、能力边界与落地前提
java·前端·人工智能·嘉为蓝鲸
白山编程大哥8 小时前
Java 后端如何优雅地把 List 集合返回给前端
java·前端·list
Flynt9 小时前
我把热榜那篇"禁用 axios"逐条实测了一遍:结论大体对,坑在它没讲的地方
前端·javascript·axios
Csvn9 小时前
bundle优化
前端
slongzhang_10 小时前
linux 递归删除源码文件|递归删除目录下 *.js,但排除 *.min.js
linux·开发语言·javascript
北冥有鱼10 小时前
发版后动态路由点击报 `Failed to fetch dynamically imported module`」问题上的完整排查与修复过程
前端·vue.js
静默回滚10 小时前
视频压到 25 MB 以内,码率要算、音轨要扣、余量要留
前端