xmlhttprequest 直接请求不同源接口会失败,因为浏览器同源策略默认拦截跨域请求;协议、域名、端口任一不同即被拒绝,错误提示为“blocked by cors policy”,根源在于服务端未返回access-control-allow-origin响应头。

为什么 XMLHttpRequest 直接请求不同源接口会失败
浏览器的同源策略(Same-Origin Policy)默认拦截跨域的 XMLHttpRequest 和 fetch 请求,哪怕只是协议、端口、域名中任一不同,都会被拒绝。典型错误是控制台报 Blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present —— 这不是前端代码写错了,而是服务端没配响应头。
常见误区是以为加个 withCredentials: true 就能解决所有跨域问题;其实它只在服务端明确允许凭据(Access-Control-Allow-Credentials: true)且 Access-Control-Allow-Origin 不能为 * 时才生效。
- 开发阶段用本地代理(如 Webpack DevServer 的
proxy)最稳妥,不依赖后端配合 - 生产环境若后端无法改响应头,
JSONP只适用于 GET,且需服务端返回函数调用格式,已基本淘汰 -
postMessage适合 iframe 场景,但通信逻辑要自己设计,不是通用 API 调用方案
如何用 nginx 反向代理绕过浏览器 CORS 限制
本质是让前端请求看起来“同源”:把 /api/xxx 代理到真实后端地址,由 nginx 完成跨域转发。浏览器只看到自己域名下的请求,不触发 CORS 检查。
关键点在于 location 配置和 header 透传:
location /api/ {
proxy_pass https://real-api.example.com/;
proxy_set_header Host $host;
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;
}
- 注意
proxy_pass末尾斜杠:带斜杠会剥离/api前缀;不带则原样拼接 - 如果后端需要识别原始协议(如生成 HTTPS 链接),必须设
X-Forwarded-Proto - 不要在 nginx 里硬加
Access-Control-Allow-Origin——这解决的是预检请求(OPTIONS),但掩盖了真正的问题:后端本该自己控制跨域策略
fetch 发送带 cookie 的跨域请求总失败?检查这三个地方
只要涉及登录态传递,credentials 选项就绕不开。但光写 credentials: 'include' 不够,三处必须同时满足:
- 前端
fetch中显式设置credentials: 'include'(默认是'omit') - 服务端响应头包含
Access-Control-Allow-Credentials: true - 服务端的
Access-Control-Allow-Origin不能是通配符*,必须精确匹配当前域名,例如https://myapp.com
漏掉任意一条,浏览器就会静默丢弃响应,控制台可能只显示 Failed to fetch,没有更具体的提示。
Vue 或 React 项目中配置代理为什么只在开发生效
Webpack/Vite 的 devServer.proxy 或 vite.config.ts 中的 server.proxy 是纯开发时的本地中间件,打包后代码运行在用户浏览器里,这些配置完全不生效。
上线前必须确认:
- 生产环境是否已部署对应 nginx 代理规则(或使用云厂商的 API 网关路由)
- 环境变量(如
VUE_APP_BASE_API)是否在构建时正确注入,避免开发用/api、生产直连https://api.xxx导致跨域 - 若用微前端,主应用与子应用跨域通信需额外处理
window.postMessage或CustomEvent,不能指望代理解决
跨域从来不是前端单方面能“解决”的问题,它本质是前后端协作边界问题。最容易被忽略的是预检请求(OPTIONS)被防火墙或 CDN 拦截,或者服务端框架(如 Express、Spring Boot)默认未开启 CORS 支持,只配了 Nginx 却忘了后端本身也要放行。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











