现在的web应用越来越丰富,一个web上的内容往往会抓取其他web上的数据。在默认情况下,web上的交互需要遵循同源策略(Same-origin policy),即同协议、同域名、同端口。在URLhttp://store.company.com/dir2/other.html
中,协议是Http、域名是store.company.com,端口是80。当不符合同源策略时,这时的通信就可以叫做跨域通信。跨域通信有许多奇奇怪怪的方法可以做到,这里就简单介绍几种。
document.domain + iframe
http://www.a.com
和http://script.a.com
的交互是跨域交互,因为两者域名不同,虽然主域名都为a.com
。
对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上`document.domain = ‘a.com’;然后通过在a.html文件中创建一个
1 | //www.a.com/a.html |
1 | //script.a.com/b.html |
JSONP
JSONP(JSON with padding)利用<script>
跨域加载脚本的原生能力来做到跨域通信。
我们知道,如果要引用JQuery库,除了下载到本地引入外,还可以这么引入:<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
,这个就是JSONP的基本原理。JSONP是一种非正式的传输协议,可以说是劳动人民的智慧。在JSONP的跨域通信中,客户端和服务器都需要遵循一定的规则。
<script>
的src属性应该填入所需服务的URL,URL中有查询字符串code=CA998&jsoncallback=callbackFunction
,code=CA998
是传送给服务器的数据,jsoncallback=callbackFunction
是传送给服务器的回调函数。前者jsoncallback由服务器定义,可能是callback、callbackFunc等等,双方约定好即可。后者callbackFunction由客户端定义,这是一个回调函数。将这样一个查询字符串发送给服务器之后,服务器会做两件事:1.根据查询字符串中的数据,准备好客户端需要的结果数据;2.将数据传入回调函数,把执行函数的字符串返回给客户端。客户端加载入这样一个js文件后,会执行该js文件中的执行语句。
服务器返回了带有执行语句的js,在客户端这边,需要定义或者声明这个回调函数callbackFunction()
。
1 | //回调函数 |
1 | //服务器根据查询字符串的请求,用服务器端的语言,生成并返回js文件,该js文件大概内容如下 |
HTML5 postMessage
HTML5为window对象新增了一个postMessage方法,该方法用于解决跨域通信的问题。
在http://test.com
下,向http://lslib.com
发送信息的步骤:
1.在发送方建立<iframe>
,src
属性填写接收方的url
2.调用frame的postMessage()方法,该方法接收两个参数:
message:只支持字符串信息,若要发送对象,可用JSON.stringify转换成字符串;
targetOrigin:目标域
3.在接收端为window对象绑定message事件,MessageEvent对象有三个重要的属性:
data:获取字符串
source:发送消息的窗口对象
origin:发送消息的源
1 | http://test.com/index.html |
1 | http://lslib.com/lslib.html |
图像ping
一个网页可以从其他任何网页中加载图,那么图像ping主要通过<img>
标签的src属性来进行跨域。客户端的请求通过查询查询字符串发送给服务器。这种方式主要有两点不足:1.只能用Get请求;2.只能进行客户端至服务器的单向通信(通过查询字符串),无法访问服务器的响应文本。
1 | var img = new Image(); |
【Reference】