跨域请求被浏览器同源策略拦截,服务端实际已接收并响应;CORS预检失败因后端未正确配置Access-Control-Allow-Origin等响应头;开发可配vite/webpack代理临时解决,JSONP已淘汰。

跨域请求不是“不安全所以被禁”,而是浏览器出于同源策略(Same-Origin Policy)主动拦截了 JavaScript 发起的跨域 XMLHttpRequest 或 fetch 请求——服务端其实完全收到了请求,也正常返回了响应,但浏览器拒绝把响应内容交给 JS 脚本。
为什么 fetch 会报 “No 'Access-Control-Allow-Origin' header” 错误
这是典型的 CORS(Cross-Origin Resource Sharing)预检失败提示。浏览器在发送某些“非简单请求”(如带 Content-Type: application/json、自定义 header、PUT/DELETE 方法)前,会先发一个 OPTIONS 预检请求。如果后端没正确响应这个 OPTIONS,或者没返回必需的 CORS 头,fetch 就会直接报错,连真正的请求都不会发出去。
- 必须由后端设置响应头:
Access-Control-Allow-Origin(不能是通配符*+ 凭据) - 若前端带
credentials: 'include',后端还必须加:Access-Control-Allow-Credentials: true - 预检请求要求后端对
OPTIONS返回 200,并带上Access-Control-Allow-Methods和Access-Control-Allow-Headers
前端临时绕过:开发环境用 webpack/vite 代理
代理只在开发服务器生效,不解决生产跨域,但能立刻让接口调通,避免反复改后端配置。
- vite:在
vite.config.ts中配server.proxy,例如将/api代理到http://localhost:3000 - webpack-dev-server:在
devServer.proxy中写对象或数组规则,注意路径重写(rewrite或pathRewrite已废弃,改用configure函数) - 关键点:代理目标地址不能带结尾斜杠(
target: 'http://localhost:3000'✅,'http://localhost:3000/'❌),否则路径拼接错
JSONP 已淘汰,不要在新项目中使用
JSONP 利用 标签不受同源限制的特性,通过动态插入 script 加载远程 JS 执行回调。但它只支持 GET,没有错误捕获机制,无法设 timeout,且服务端必须配合返回函数调用格式(如 callback({...}))。现代浏览器已弃用 document.write,主流框架也不再内置 JSONP 支持。
立即学习“Java免费学习笔记(深入)”;
- 如果你看到老代码里还有
$.getJSON(url + '?callback=?')或手动创建script标签,说明它没走 CORS,而是降级到了 JSONP - Chrome 98+ 对
document.write在非初始页面加载时直接静默忽略,JSONP 回调可能永远不执行 - 真正需要兼容 IE10 及以下?优先考虑后端加 CORS,而不是复活 JSONP
fetch('/api/user', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ id: 123 })
})
.then(r => r.json())
.catch(err => console.error('网络或 CORS 失败:', err))
CORS 的核心从来不在前端“怎么发”,而在于后端是否明确声明“允许谁、用什么方法、带什么头来访问我”。很多前端开发者卡在“为什么本地能通上线就跨域”,往往是因为 nginx 或云函数网关没透传后端返回的 CORS 响应头,或者反向代理覆盖了它们。










