js for data transmission or communication across domains

Today, I saw an article about JS cross-domain. It is very detailed, so I can record it so that I can check it later when I use it.

[Reprint] The js cross-domain mentioned here refers to the data transmission or communication between different domains through js, such as requesting data from a different domain with ajax, or obtaining the frame (iframe) of different domains in the page through js The data. As long as the protocol, domain name, and port are different, they are regarded as different domains.

The following table gives the results of the homology test relative to http://store.company.com/dir/page.html:

QQ screenshot 20130613230631

To solve the problem of cross-domain, we can use the following methods:

1. Cross-domain through jsonp

In js, when we directly request data on different domains with XMLHttpRequest, it is not possible. However, it is possible to introduce js script files on different domains on the page, and jsonp uses this feature to achieve it.

For example, there is an a.html page, the code in it needs to use ajax to obtain json data on a different domain, assuming that the json data address is http://example.com/data.php , then the code in a.html Just like this:

QQ screenshot 20130613230631

We see that there is a callback parameter after the address where the data is obtained. By convention, this parameter name is used, but you can use other parameters as well. Of course, if the jsonp address page for obtaining data is not under your control, you have to operate in the format specified by the party providing the data.

Because it is imported as a js file, the return of http://example.com/data.php must be an executable js file, so the php code of this page may look like this:

QQ screenshot 20130613230631

The final output of that page is:

QQ screenshot 20130613230631

So the js file obtained through http://example.com/data.php?callback=dosomething is the dosomething function we defined earlier, and its parameters are the json data we need, so that we can get the cross domain we need The data.

In this way, the principle of jsonp is very clear. A js file is introduced through the script tag. After the js file is loaded successfully, the function specified in the url parameter will be executed, and the json data we need will be passed in as a parameter. So jsonp needs the corresponding cooperation of the server-side page.

After knowing the principle of jsonp cross-domain, we can use js to dynamically generate script tags for cross-domain operations, instead of manually writing those script tags. If your page uses jquery, then it is very convenient to perform jsonp operations through the method it encapsulates.

QQ screenshot 20130613230631

The principle is the same, but we don't need to manually insert script tags and define callback functions. jQuery will automatically generate a global function to replace the question mark in callback=?, and then it will be automatically destroyed after obtaining the data, which actually acts as a temporary proxy function. The $.getJSON method will automatically determine whether it is cross-domain. If it is not cross-domain, it will call the ordinary ajax method; if it is cross-domain, it will call the jsonp callback function in the form of asynchronously loading the js file.

 

2. Cross subdomains by modifying document.domain

浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。有一点需要说明,不同的框架之间(父子或同辈),是能够获取到彼此的window对象的,但蛋疼的是你却不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外,还有些浏览器比如ie6也可以使用top、parent等少数几个属性),总之,你可以当做是只能获取到一个几乎无用的window对象。比如,有一个页面,它的地址是http://www.example.com/a.html  , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

  QQ screenshot 20130613230631

这个时候,document.domain就可以派上用场了,我们只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。

在页面 http://www.example.com/a.html 中设置document.domain:

QQ screenshot 20130613230631

在页面 http://example.com/b.html 中也设置document.domain,而且这也是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值:

QQ screenshot 20130613230631

这样我们就可以通过js访问到iframe中的各种属性和对象了。

不过如果你想在http://www.example.com/a.html 页面中通过ajax直接请求http://example.com/b.html 页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同子域的框架间的交互。如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用一个隐藏的iframe来做一个代理。原理就是让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据的,然后就是通过我们刚刚讲得修改document.domain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发送ajax请求,然后收到的数据我们也可以获得了。

 

3、使用window.name来进行跨域

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

比如:有一个页面a.html,它里面有这样的代码:

QQ screenshot 20130613230631

再看看b.html页面的代码:

QQ screenshot 20130613230631

a.html页面载入后3秒,跳转到了b.html页面,结果为:

QQ screenshot 20130613230631

我们看到在b.html页面上成功获取到了它的上一个页面a.html给window.name设置的值。如果在之后所有载入的页面都没对window.name进行修改的话,那么所有这些页面获取到的window.name的值都是a.html页面设置的那个值。当然,如果有需要,其中的任何一个页面都可以对window.name的值进行修改。注意,window.name的值只能是字符串的形式,这个字符串的大小最大能允许2M左右甚至更大的一个容量,具体取决于不同的浏览器,但一般是够用了。

上面的例子中,我们用到的页面a.html和b.html是处于同一个域的,但是即使a.html与b.html处于不同的域中,上述结论同样是适用的,这也正是利用window.name进行跨域的原理。

下面就来看一看具体是怎么样通过window.name来跨域获取数据的。还是举例说明。

比如有一个www.example.com/a.html页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面www.cnblogs.com/data.html里的数据。

data.html页面里的代码很简单,就是给当前的window.name设置一个a.html页面想要得到的数据值。data.html里的代码:

QQ screenshot 20130613230631

那么在a.html页面中,我们怎么把data.html页面载入进来呢?显然我们不能直接在a.html页面中通过改变window.location来载入data.html页面,因为我们想要即使a.html页面不跳转也能得到data.html里的数据。答案就是在a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据。

充当中间人的iframe想要获取到data.html的通过window.name设置的数据,只需要把这个iframe的src设为www.cnblogs.com/data.html就行了。然后a.html想要得到iframe所获取到的数据,也就是想要得到iframe的window.name的值,还必须把这个iframe的src设成跟a.html页面同一个域才行,不然根据前面讲的同源策略,a.html是不能访问到iframe里的window.name属性的。这就是整个跨域过程。

看下a.html页面的代码:

上面的代码只是最简单的原理演示代码,你可以对使用js封装上面的过程,比如动态的创建iframe,动态的注册各种事件等等,当然为了安全,获取完数据后,还可以销毁作为代理的iframe。网上也有很多类似的现成代码,有兴趣的可以去找一下。

通过window.name来进行跨域,就是这样子的。

 

4、使用HTML5中新引进的window.postMessage方法来跨域传送数据

window.postMessage(message,targetOrigin)  方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 *  。

需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

The above-mentioned sending messages to other window objects actually refers to the situation where a page has several frames, because each frame has a window object. When discussing the second method, we said that frameworks of different domains can obtain each other's window objects, and the method window.postMessage can also be used. Let's look at a simple example with two pages

QQ screenshot 20130613230631

 

QQ screenshot 20130613230631

The result we get after running a page:

QQ screenshot 20130613230631

We see that the b page has successfully received the message.

It is more intuitive and convenient to use postMessage to transmit data across domains, but the disadvantage is that IE6 and IE7 do not support it, so whether to use it or not has to be decided according to actual needs.

 

Conclusion:

In addition to the above methods, there are also cross-domain methods such as flash and setting proxy pages on the server, which will not be introduced here.

The above four methods can be selected and applied according to the actual situation of the project. I personally think that the method of window.name is not complicated and is compatible with almost all browsers. This is really an excellent cross-domain method.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325987688&siteId=291194637