> 技术文档 > 前端常见跨域解决方案汇总

前端常见跨域解决方案汇总


跨域解决方案

跨域(Cross-Origin Resource Sharing,CORS)是前端开发中非常常见的问题。当协议、域名或端口不同时,就会产生跨域。浏览器出于安全考虑,会阻止跨域请求。

以下是几种常见的跨域解决方案,从最常见到较少使用的顺序排列:

1. CORS (跨域资源共享) - 主流标准方案

这是 W3C 标准,也是最推荐、最主流的跨域解决方案。它需要服务器和浏览器协同工作

  • 原理:服务器通过设置 HTTP 响应头(如 Access-Control-Allow-Origin)来告诉浏览器,允许哪些源、方法或头信息可以访问资源。
  • 实现方式
    • 简单请求:浏览器直接发出请求,服务器返回 Access-Control-Allow-Origin: *Access-Control-Allow-Origin: https://example.com 等头部。
    • 非简单请求:浏览器会先发送一个 OPTIONS 方法的“预检请求”,询问服务器是否允许实际请求。服务器确认后,浏览器才会发送真正的请求。
  • 示例(Node.js/Express 服务器端设置)
    // 设置允许所有源访问(不推荐在生产环境使用 *)app.use((req, res, next) => { res.setHeader(\'Access-Control-Allow-Origin\', \'*\'); res.setHeader(\'Access-Control-Allow-Methods\', \'GET, POST, PUT, DELETE\'); res.setHeader(\'Access-Control-Allow-Headers\', \'Content-Type, Authorization\'); next();});// 更安全的做法是动态设置允许的源const allowedOrigins = [\'https://www.a.com\', \'https://www.b.com\'];app.use((req, res, next) => { const origin = req.headers.origin; if (allowedOrigins.includes(origin)) { res.setHeader(\'Access-Control-Allow-Origin\', origin); } res.setHeader(\'Access-Control-Allow-Methods\', \'GET, POST, OPTIONS\'); res.setHeader(\'Access-Control-Allow-Headers\', \'Content-Type\'); next();});

2. JSONP (JSON with Padding) - 传统方式

一种古老的跨域技术,现在已不常用,主要用于兼容老式浏览器。仅支持 GET 请求

  • 原理:利用 标签没有跨域限制的特点,通过动态创建 script 标签,请求一个带参网址,服务器收到请求后,将数据放在一个指定名字的回调函数里返回。
  • 实现方式
    1. 前端定义全局回调函数,并动态创建 script 标签,将回调函数名作为参数传递给服务器。
    2. 服务器接收参数,将数据用该回调函数名包裹后返回(例如 callbackFunction({data: ...}))。
    3. 返回的脚本会被浏览器立即执行,从而触发前端定义的回调函数。
  • 缺点:只支持 GET,错误处理困难,存在安全风险(如果服务器返回恶意代码)。

3. 反向代理 - 开发/部署常用

这是在开发阶段和生产环境部署时都非常常用且实用的方案。前端开发者自己就可以解决,无需后端大量修改代码。

  • 原理:跨域是浏览器的限制,服务器之间没有跨域问题。反向代理服务器位于前端应用和后台API服务器之间。对浏览器来说,请求的是同源的代理服务器,代理服务器再偷偷地去请求真正的目标服务器,拿到结果后再返回给浏览器。
  • 实现方式
    • 开发环境:使用 Webpack Dev Server、Vite 等工具提供的 proxy 配置。
      // vite.config.js / webpack.config.jsexport default defineConfig({ server: { proxy: { \'/api\': { target: \'http://api.example.com\', // 目标服务器地址 changeOrigin: true, rewrite: (path) => path.replace(/^\\/api/, \'\') } } }});

      这样,你在前端代码中请求 /api/users,开发服务器会代理到 http://api.example.com/users

    • 生产环境:使用 Nginx 等服务器软件进行配置。
      # nginx.confserver { listen 80; server_name my-frontend.com; location /api/ { proxy_pass http://my-backend.com/; # 代理到后端服务器 }}

4. WebSocket

WebSocket 协议本身允许跨域连接,不受浏览器同源策略的限制。

  • 原理:WebSocket 是一种双向通信协议,在建立连接时的握手阶段使用 HTTP 协议,但一旦连接建立,通信就不受同源策略约束。
  • 适用场景:适用于需要服务器主动向客户端推送数据的场景(如聊天室、实时游戏、股票行情),而不仅仅是解决普通的 API 跨域请求。

5. 其他方式(了解即可)

  • postMessage:主要用于不同窗口/iframe 之间的通信(例如,页面与内嵌的 iframe 通信),也可以用于解决跨域问题。
  • document.domain:仅适用于主域相同、子域不同的情况(例如 a.example.comb.example.com),通过将两个页面的 document.domain 都设置为 example.com 来实现跨域。已不推荐使用
  • window.name + iframe:一种利用 iframe 和 window.name 特性传递数据的 Hack 方式,非常古老且不优雅。

总结与推荐

方式 优点 缺点 适用场景 CORS 标准、安全、功能强大 需要服务器端配合修改 主流方案,前后端分离的 Web 应用 JSONP 兼容老浏览器 只支持 GET,不安全,是 Hack 兼容性要求极高的老项目 反向代理 前端可自行配置,无感解决 需要部署代理服务器 开发调试前后端分离部署 WebSocket 双向通信,不受限 并非为普通 HTTP API 设计 实时双向通信应用

最佳实践建议:

  1. 首选 CORS:如果你的项目是全新的,或者可以控制后端服务器,直接使用 CORS 是最标准、最正确的做法。
  2. 开发阶段用反向代理:使用 Webpack/Vite 等工具的反向代理功能,可以极大提高开发效率,避免本地开发时的跨域烦恼。
  3. 结合使用:生产环境用 Nginx 反向代理来处理跨域和负载均衡,同时后端也可以配置更精细的 CORS 策略,双重保障。