跨域问题解决方法
跨域问题是由于浏览器的同源策略(Same-Origin Policy)导致的,它限制了不同源(协议、域名、端口任一不同)的资源交互。以下是常见解决方案,按优先级排序:
一、主流解决方案
1. CORS(跨域资源共享) ⭐️ 最推荐
- 原理:服务端设置响应头声明允许跨域。
- 实现:
// 服务端响应头示例(以 Node.js 为例) Access-Control-Allow-Origin: * // 允许所有域名(* 生产环境慎用) Access-Control-Allow-Origin: https://your-frontend.com // 指定域名 Access-Control-Allow-Methods: GET,POST,PUT // 允许的请求方法 Access-Control-Allow-Headers: Content-Type,Authorization // 允许的请求头
- 需预检的请求(如带自定义头或非简单请求):需处理
OPTIONS
预检请求。
2. 代理服务器(Proxy) ⭐️ 前端开发常用
- 原理:让同源服务器中转请求(浏览器→同源服务器→目标服务器)。
- 实现:
- 开发环境:用 webpack-dev-server / Vite 代理:
// vite.config.js export default {server: {proxy: {'/api': {target: 'http://api.example.com', // 目标服务器changeOrigin: true, // 修改请求头 Hostrewrite: path => path.replace(/^\/api/, '') // 路径重写}}} }
- 生产环境:用 Nginx 反向代理:
location /api/ {proxy_pass http://api.example.com/; # 转发到目标服务器add_header Access-Control-Allow-Origin *; # 可选,双重保障 }
- 开发环境:用 webpack-dev-server / Vite 代理:
二、特殊场景方案
3. JSONP(仅限 GET 请求)
- 原理:利用
<script>
标签不受同源策略限制的特性。 - 实现:
<!-- 前端 --> <script>function handleResponse(data) {console.log("收到数据:", data);} </script> <script src="http://api.com/data?callback=handleResponse"></script>
// 服务端返回(需支持 JSONP) handleResponse({ "data": "example" });
4. WebSocket
- 原理:WebSocket 协议本身支持跨域。
- 实现:
const socket = new WebSocket("ws://api.example.com"); socket.onmessage = event => console.log(event.data);
5. 修改 document.domain
(仅限子域跨域)
- 场景:
a.example.com
与b.example.com
通信。 - 实现:
// 在两个页面中均设置 document.domain = "example.com"; // 降域到同一父域
三、其他注意事项
-
携带 Cookie 的跨域请求:
- 前端设置:
fetch(url, { credentials: 'include' })
- 服务端需设置:
Access-Control-Allow-Credentials: true
且Access-Control-Allow-Origin
不能为*
,必须指定域名。
- 前端设置:
-
避免跨域的替代方案:
- 将前后端部署在同一域名下(如前端
example.com
,后端api.example.com
通过 Nginx 合并域名)。
- 将前后端部署在同一域名下(如前端
总结选择
场景 | 推荐方案 |
---|---|
可控的服务端 | CORS |
前端开发调试 | 本地代理(webpack/Vite) |
生产环境前后端分离 | Nginx 代理 |
仅需 GET 请求的旧系统兼容 | JSONP |
实时双向通信(如聊天室) | WebSocket |
优先使用 CORS 或 代理,其他方案作为特殊场景备选。