跳到主要内容

跨域

浏览器为了安全而限制不同源(协议、域名、端口任一不同)的脚本访问资源(如 Cookie、DOM、AJAX)。

  • 保护 DOM 安全:禁止不同源的页面操作当前页面的 DOM,比如防止恶意网站通过 iframe 嵌套网页并篡改内容
  • 保护 Cookie 安全:禁止不同源的页面读取当前页面的 Cookie(Cookie 中常储存登录状态、用于信息等敏感数据),避免身份被盗用
  • 保护数据安全:禁止不同源的脚本发起请求获取当前网络的敏感数据(比如说订单、个人信息),防止数据泄漏

一、 常见的跨域场景

  • Ajax 请求:使用 XMLHttpRequestfetch 等 API 发送跨域请求
  • 第三方服务集成:集成地图、支付服务等第三方资源
  • 单点登录:多个应用之间共享用户认证信息
  • iframe 嵌入内容:父页面与 Iframe 之间的交互
  • Web 字体:加载不同域的字体
  • Canvas 加载图片:在 Canvas 中绘制不同源的图像
  • WebGL 贴图:在 WebGL 中使用贴图也会像在 Canvas 中绘制图片一样有同源限制
  • 来自图像的 CSS 图形

二、 跨域解决方案

跨域问题需要前端和后端配合解决解决

  • CORS(跨资源共享)
  • JSONP (兼容方案,仅支持 GET)
  • 开发环境使用代理服务器

1. CORS (跨资源共享)

官方推荐,通过服务器设置相应头授权允许固定源跨域。

  • 简单请求
    • 方法:GET、POST、HEAD
    • 头部:仅允许简单头部(如 Content-Type: application/x-www-form-urlencoded
    • 流程:直接发送请求,服务器返回 Access-Control-Allow-Origin: <允许的源> (如 * 或具体的域名)即可
  • 非简单请求(如 PUT、带自定义头部)
    • 先发送 预检请求(OPTIONS),询问服务器是否允许跨域(包含方法、头部等信息)
    • 服务器返回 Access-Control-Allow-MethodsAccess-Control-Allow-Headers 等授权后,再发送实际请求

关键相应头:

  • Access-Control-Allow-Origin:允许的源(如 *https://example.com

  • Access-Control-Allow-Methods:允许的 HTTPS 方法(如 GETPOST

  • Access-Control-Allow-Headers:允许的请求

  • Access-Control-Expose-Headers:允许前端访问的额外相应头

  • 优点:标准的 W3C 方案,安全性高,支持所有的请求方法

  • 缺点:需要后台配合修改代码

2. 代理服务器

前端请求发送到本地开发服务器,由代理服务器转发到目标服务器

  • 开发服务器:Vue CLIVite 等配置代理

  • 生产环境:Nginx 反向代理

  • 优点:无需服务器支持 CORS,配置简单

  • 缺点:仅适用于开发环境(生产环境需要服务器配合配置)

3. JSONP

利用 <script> 标签不受同源策略的影响的特性

  • 客户端定义回调函数(如 handleData(data)
  • 动态创建 <script scr="https://跨域域名/api?callback=handleData">
  • 服务器返回 handleData (响应数据),客户端通过回调函数接收数据
危险
  • 仅支持 GET
  • 安全性低,无错误处理,且存在 XSS 风险
  • 无法获取相应头和状态码

4. postMessage

HTML5 提供的跨域通信 API,通过 postMessage() 方法进行不同源页面之间的通信。

  • A 页面向 B 页面发送消息:iframe.contentWindow.postMessage(data, '*')

  • B 页面监听消息:window.addEventListener('message', callback)

  • 优点:安全、灵活、支持所有的浏览器

  • 缺点:需要双方页面都进行相应的处理

5. document.domain + iframe

通过设置同一主域下不同子域的 document.domain 为相同的源,即可完成跨域。

  • 优点:无需后端配合
  • 缺点:仅适用于同一主域,不支持跨主域

6. WebSocket -- 全双工跨域通信

webSocket 是独立于 HTTP 协议( ws://wss://),建立连接后浏览区域服务器可全双工通信,且不受同源策略的限制。适用于实时聊天的通信场景。

  • 优点:实时性强,全双工通信,不受同源限制
  • 缺点:需后端支持 WebSocket 协议,不适合简单的 HTTP 请求的场景