Skip to content
扫码联系作者

跨域解决方案

跨域的概念

跨域(Cross-Origin)是指在Web开发中,一个域(网站的源)的JavaScript代码试图访问另一个域的资源,而这个资源可能位于不同的域名、端口或协议下。域是由协议、主机名和端口号组成的,只有这三者完全相同的两个网址才属于同一个域。 跨域请求是由浏览器的同源策略(Same-Origin Policy)所限制的。同源策略是浏览器的一种安全机制,它防止一个域中的Web页面从另一个域中获取数据,或与另一个域进行交互,以防止恶意网站利用跨域漏洞进行攻击。 具体来说,同源策略要求以下信息完全相同,才被视为同源:

  1. 协议(Protocol):即URL的开头部分,如http、https等。
  2. 域名(Host):URL中的域名部分。
  3. 端口(Port):URL中的端口部分。

如果上述三者中有任何一个不同,就被视为跨域。

JSONP

JSONP(JSON with Padding)是一种利用<script>标签实现的跨域数据请求技术,允许页面从不同域的服务器请求数据并获取执行。

原理:

  1. 客户端在页面中创建一个<script>标签,并指定请求的URL,该URL由服务器返回JSON数据包装在一个函数调用中。
  2. 服务器接收到JSONP请求后,将数据以参数形式包装在指定的回调函数中,并作为JavaScript代码返回给客户端。
  3. 客户端接收到响应后,会直接执行返回的JavaScript代码,从而触发回调函数,并处理获取到的数据。

CORS

CORS(Cross-Origin Resource Sharing)是一种现代化的跨域解决方案,它允许Web服务器在响应中声明允许哪些域的客户端来访问资源。

原理:

  1. 浏览器在发送跨域请求时,会自动在请求头中添加Origin字段,该字段指示该请求的源(域)。
  2. 服务器接收到请求后,根据Origin字段判断是否允许该域访问资源。
  3. 如果服务器允许该域访问资源,需要在响应头中添加Access-Control-Allow-Origin字段,并将其设置为允许的源,可以是具体的域名,也可以是通配符*表示允许任意域访问。
  4. 服务器还可以在响应头中添加其他CORS相关字段,如Access-Control-Allow-Methods(允许的HTTP方法)、Access-Control-Allow-Headers(允许的请求头)、Access-Control-Allow-Credentials(是否允许发送凭证)等。

postMessage

postMessage是HTML5引入的一种跨文档通信技术,它允许在不同窗口或iframe之间安全地传递消息。通过postMessage,可以在跨域的页面之间进行双向通信,实现数据的传递和交互。

原理:

  1. 在发送消息的窗口(发送消息的页面或iframe)中调用postMessage()方法,向目标窗口发送消息。该方法接受两个参数:要发送的数据和目标窗口的源(origin)。
  2. 目标窗口中通过监听message事件来接收消息。当接收到消息时,可以获取发送的数据并进行处理。

WebSocket

使用WebSocket进行跨域通信是一种高效的实时通信解决方案,它允许在不同域之间建立全双工的实时连接。WebSocket协议自带跨域功能,不受同源策略限制,因此可以轻松地在不同域的页面间进行通信。

原理:

  1. 客户端通过HTTP请求发送一个特殊的握手请求到WebSocket服务器,请求头中包含Upgrade字段,值为"websocket",表示希望升级到WebSocket协议。
  2. WebSocket服务器接收到握手请求后,如果支持WebSocket协议,会返回一个101状态码,表示同意升级到WebSocket。
  3. 连接升级成功后,客户端和服务器之间建立了WebSocket连接,双方可以通过该连接进行全双工的实时通信,可以发送和接收数据。

document.domain+iframe

使用document.domain和iframe结合的方式是一种简单的跨域通信解决方案,适用于在同一顶级域名下的子域之间进行跨域通信。该方法要求主页面和子页面都设置相同的顶级域名,并使用document.domain进行设置。

原理:

  1. 主页面和子页面都位于相同的顶级域名下(例如,主页面为https://example.com,子页面为https://sub.example.com)。
  2. 主页面和子页面通过在页面的JavaScript代码中分别设置document.domain,将其值设置为相同的顶级域名(即example.com),这样它们就共享了相同的域,成为同一域。
  3. 主页面中的JavaScript代码可以通过iframe元素获取子页面的window对象,并与子页面进行通信。

window.name

使用window.name实现跨域通信是一种较为古老但简单有效的跨域解决方案,它适用于在同一个浏览器窗口(或标签页)下进行跨域通信。

原理:

  1. 当页面跳转到不同域的页面时,浏览器会刷新window对象,但是window.name属性会保留之前的值。
  2. 通过在一个页面中设置window.name,然后在同一窗口中打开另一个不同域的页面,在该页面中可以读取前一个页面设置的window.name值,实现跨域通信。

location.hash

使用location.hash实现跨域通信是一种比较简单的跨域解决方案。它适用于在同一个浏览器窗口(或标签页)下进行跨域通信,并且可以在URL中传递少量数据。

原理:

  1. 当页面跳转到不同域的页面时,浏览器会刷新window对象,但是location.hash属性会保留之前的值。
  2. 通过在一个页面中设置location.hash,然后在同一窗口中打开另一个不同域的页面,在该页面中可以读取前一个页面设置的location.hash值,实现跨域通信。

Node代理

使用Node.js代理是一种常见且强大的跨域解决方案。通过在Node.js服务器端进行代理,可以实现在客户端发送跨域请求时将请求转发到目标服务器,并将响应返回给客户端,从而绕过浏览器的同源策略。

原理:

  1. 客户端发送跨域请求到Node.js服务器。
  2. Node.js服务器接收到请求后,通过HTTP模块或者其他请求库,将请求转发到目标服务器。
  3. 目标服务器处理请求并返回响应数据给Node.js服务器。
  4. Node.js服务器将目标服务器的响应数据返回给客户端。

Nginx代理

使用Nginx代理也是一种常见的跨域解决方案。Nginx是一个高性能的Web服务器和反向代理服务器,通过配置Nginx服务器来实现代理,可以将客户端发送的跨域请求转发到目标服务器,并将目标服务器的响应返回给客户端,从而绕过浏览器的同源策略。

原理:

  1. 客户端发送跨域请求到Nginx服务器。
  2. Nginx服务器根据配置的代理规则,将请求转发到目标服务器。
  3. 目标服务器处理请求并返回响应数据给Nginx服务器。
  4. Nginx服务器将目标服务器的响应数据返回给客户端。

CORS Anywhere

CORS Anywhere是一个开源的跨域解决方案,它是一个反向代理服务器,通过在服务器端转发请求并添加CORS头部,实现跨域资源共享。CORS Anywhere允许客户端从一个域名发出跨域请求,并将请求转发到目标服务器,然后将目标服务器的响应返回给客户端,从而绕过浏览器的同源策略。

原理:

  1. 客户端发送跨域请求到CORS Anywhere服务器。
  2. CORS Anywhere服务器接收到请求后,通过在服务器端向目标服务器发送请求,并将目标服务器的响应数据返回给客户端

对比与总结

  1. JSONP:

优点:简单易用,兼容性好。

缺点:只支持GET请求,安全性较差。

  1. CORS:

优点:支持所有HTTP请求方法,更安全,服务器有更细粒度的控制。

缺点:兼容性较JSONP稍差,在老旧浏览器上可能不支持。

  1. postMessage:

优点:安全性好,适用于不同窗口或iframe之间的跨域通信。

缺点:需要在通信双方都实现postMessage处理。

  1. WebSocket:

优点:实时性好,适用于实时通信场景,不受同源策略限制。

缺点:需要服务器支持WebSocket协议。

  1. document.domain+iframe:

优点:简单易用,适用于同一顶级域名下的子域之间进行跨域通信。

缺点:限制较多,只适用于同一顶级域名下的子域之间。

  1. window.name:

优点:兼容性好;操作简单。

缺点:数据量小;只适用于同窗口。

  1. location.hash:

优点:简单易用,适用于同一窗口(或标签页)下的跨域通信。

缺点:数据传递在URL中,数据量有限,适合传递少量信息。

  1. Node.js代理:

优点:配置灵活,跨域请求的处理逻辑移到服务器端,不受同源策略限制。

缺点:需要搭建Node.js服务器并进行开发,对于前端开发者可能涉及到服务器的知识。

  1. Nginx代理:

优点:配置灵活,跨域请求的处理逻辑移到服务器端,更易维护和管理,不受同源策略限制。

缺点:需要搭建Nginx服务器并配置,对于前端开发者可能涉及到服务器的知识。

  1. CORS Anywhere:

优点:简单易用,不需要前后端都实现特殊处理,可以绕过浏览器的同源策略。

缺点:需要部署CORS Anywhere服务器。

根据不同的需求和场景,选择合适的跨域解决方案。通常情况下,优先考虑使用CORS或JSONP,因为它们是浏览器原生支持的跨域解决方案。如果需要实时通信,可以考虑WebSocket。如果需要在不同域之间代理请求,可以使用Nginx代理或Node.js代理。对于子域间的跨域通信,可以使用document.domain+iframe或location.hash。如果只是临时的跨域请求,CORS Anywhere是一个快速简便的解决方案。在实际开发中,还应考虑安全性和性能方面的因素,避免出现安全漏洞或性能问题。