跨域大概是前端被问得最多、也最容易懵的问题。每次出问题的报错长得都差不多,原因却五花八门。这篇把原理和排查套路一次讲清,以后再遇到可以直接按流程走。
先搞清:浏览器在拦你,不是服务器拒绝你
同源策略是浏览器的行为。跨域请求其实发出去了、服务器也处理了、响应也回来了,只是浏览器检查响应头里没有"许可",把结果扣下了。所以用 Postman/curl 测接口一切正常、浏览器里就报错,这不是玄学。
排查流程
- F12 Network 面板,找到那条红色请求,看响应里有没有
Access-Control-Allow-Origin - 如果是 GET/POST 之外的方法(PUT/DELETE)或带了自定义 header,先看是不是 预检(OPTIONS)请求失败——真正被拦的往往是预检
- Console 里那句报错别只看最后半句,前面写了具体原因:Origin 不在许可列表、header 不被允许、还是证书问题
三种解决方案
方案一:后端配 CORS 响应头(正解)
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400 # 预检结果缓存,减少 OPTIONS 请求
带 cookie 的话,前端要设 credentials: 'include',后端响应 Access-Control-Allow-Credentials: true,且 Origin 不能写 *,必须精确域名。这是最常见的坑。
方案二:Nginx 反向代理(前端域下转发)
location /api/ {
proxy_pass http://后端内网地址:8080/;
}
浏览器请求的是同源地址,压根不构成跨域。代价是多一层转发,生产上要注意大文件上传的超时配置。
方案三:开发环境 proxy(仅本地)
// vite.config.js
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
原理同上,webpack/vite 的 dev server 帮你转发。注意它只在开发时有效,上线后没有这层,环境变量里接口地址别写死 localhost。
几个非典型"跨域"报错
- 报 CORS 错但后端确实配了:检查响应是不是 500/404——错误响应没走 CORS 拦截器的逻辑,header 没带上,浏览器报跨域,其实根因是后端异常
- JSONP:上古技术,现在基本不用,但面试还爱问。原理是 script 标签不受同源策略限制
- 跨域不影响 <script>、<img>、<link> 加载资源,这就是为什么 CDN 的 JS/CSS 能随便引

Comments 4 条评论
带 cookie 时 Origin 不能写星号,坑深
500 响应没带 CORS 头也会报跨域,涨知识
预检请求失败才是真被拦的那个
跨域不影响 script 和 img,确实