Home >Web Front-end >JS Tutorial >Comprehensive introduction to two cross-domain technologies in JavaScript_javascript skills

Comprehensive introduction to two cross-domain technologies in JavaScript_javascript skills

WBOY
WBOYOriginal
2016-05-16 16:52:101331browse

This policy places important restrictions on the page content that JavaScript code can access, that is, JavaScript can only access content in the same domain as the document that contains it.

JavaScript security strategy is particularly important when performing multi-iframe or multi-window programming, as well as Ajax programming. According to this policy, JavaScript code contained in pages under baidu.com cannot access page content under the google.com domain name; even pages between different subdomains cannot access each other through JavaScript code. The impact on Ajax is that Ajax requests implemented through XMLHttpRequest cannot submit requests to different domains. For example, pages under abc.example.com cannot submit Ajax requests to def.example.com, etc.

However, when doing some in-depth front-end programming, cross-domain operations are inevitably required. At this time, the "same origin policy" becomes too harsh. This article summarizes some technologies required for cross-domain on this issue.

Below we discuss cross-domain technology in two situations: first, we discuss cross-domain technology in different subdomains, and then we discuss cross-domain technology in completely different domains.

(1) Cross-domain technologies in different subdomains.

We will discuss two issues separately: the first issue is how to make JavaScript calls across different subdomains; the second issue is how to submit Ajax requests to different subdomains.

Let’s solve the first problem first. Suppose there are two different subdomains under the example.com domain: abc.example.com and def.example.com. Now suppose there is a page under def.example.com, which defines a JavaScript function:

Copy the code The code is as follows:
function funcInDef() {
.....
}

We want to call the above function in a page under abc.example.com. Suppose that the page under abc.example.com we want to discuss is embedded in the page under def.example.com in the form of an iframe. In this case, we may try to make the following call in the iframe:

Copy code The code is as follows:
window.top.funcInDef();

Okay, we noticed , this call is prohibited by the "same origin policy" mentioned earlier, and the JavaScript engine will directly throw an exception.
In order to implement the above call, we can do it by modifying the domain attributes of the two pages. For example, we can add the following JavaScript code snippets to the top of the two pages above abc.example.com and def.example.com:
Copy Code The code is as follows:
document.domain = "example.com";

In this way, the two pages become the same domain, and the previous calls can be executed normally.

One thing to note here is that the document.domain attribute of a page can only be set to a higher-level domain name (except for the first-level domain name), but cannot be set to a subdomain deeper than the current domain name. For example, the page abc.example.com can only set its domain to example.com, not sub.abc.example.com, and of course it cannot be set to the first-level domain name com.

The above example discusses the case where two pages belong to an iframe nested relationship. When the two pages have an open and opened relationship, the principle is exactly the same.

Let’s solve the second problem: how to submit Ajax requests to different subdomains.
Normally, we will use code similar to the following to create an XMLHttpRequest object:

Copy code The code is as follows:
factories = [function() {
return new XMLHttpRequest();
},
function() {
return new ActiveXObject("Msxml2.XMLHTTP");
},
function() {
return new ActiveXObject("Microsoft.XMLHTTP");
}];
function newRequest() {
for (var i = 0; i & lt; factories.length; i ) {
try {
var factory = factories[i];
return factory();
} catch(e) {}
}
return null;
}

The above code references ActiveXObject for compatibility with IE6 series browsers. Every time we call the newRequest function, we get a newly created Ajax object, and then use this Ajax object to send an HTTP request. For example, the following code sends a GET request to abc.example.com:
Copy the code The code is as follows:

var request = newRequest();
request.open("GET", "http://abc.example.com" );
request.send(null);

Assuming that the above code is included in a page under the abc.example.com domain name, the GET request can be sent successfully without any problems. However, if we now send a request to def.example.com, a cross-domain issue occurs and the JavaScript engine throws an exception.
The solution is to place a cross-domain file under the def.example.com domain, assuming it is called crossdomain.html; then move the definition of the previous newRequest function to this cross-domain file; and finally modify the document as before. The domain value is the same. At the top of the crossdomain.html file and the page that calls Ajax under the abc.example.com domain, add:

Copy code The code is as follows:
document.domain = "example.com";


In order to use cross-domain files, we call Ajax under the abc.example.com domain Embed a hidden iframe pointing to a cross-domain file in the page, for example:
Copy the code The code is as follows:


At this time, the page under the abc.example.com domain and the cross-domain file crossdomain.html are both under the same domain (example.com). We can call crossdomain.html in the page under the abc.example.com domain. The newRequest function in:
Copy code The code is as follows:
var request = window.frames["xd_iframe" ].newRequest();

The request object obtained in this way can send an HTTP request to http://def.example.com.

(2) Cross-domain technologies in completely different domains.

If the top-level domain names are different, for example, example1.com and example2.com want to communicate on the front end through JavaScript, the required technology is more complicated.

Before explaining the cross-domain technology of different domains, let us first make it clear that the technology to be discussed below is also applicable to the previous situation across different sub-domains, because crossing different sub-domains is only a special case of cross-domain problems. . Of course, using the right technology under the right circumstances can ensure better efficiency and higher stability.

In short, according to different cross-domain requirements, cross-domain technologies can be classified into the following categories:
1. JSONP cross-domain GET request
2. Cross-domain implementation through iframe
3. Flash cross-domain HTTP request
4. window.postMessage
Various technologies are introduced in detail below.
1. JSONP.
The method of submitting HTTP requests to different domains by creating <script> nodes in the page is called JSONP. This technology can solve the problem of submitting Ajax requests across domains. The working principle of JSONP is as follows: <br> Assuming that a GET request is submitted to http://example2.com/getinfo.php in the page http://example1.com/index.php, we can put the following JavaScript code Place it in the page http://example1.com/index.php to implement: <br></p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="91817" class="copybut" id="copybut91817" onclick="doCopy('code91817')"><u>Copy the code</u></a></span> The code is as follows:</div> <div class="codebody" id="code91817">var eleScript= document.createElement("script");<br>eleScript.type = "text/javascript";<br>eleScript.src = "http://example2.com/getinfo.php"; <br>document.getElementsByTagName("HEAD")[0].appendChild(eleScript);</div> <p>当GET请求从http://example2.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://example1.com/index.php页面中的一个callback函数。<br><br>JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。<br><br>JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。</p> <p><strong>2. 通过iframe实现跨域。<br><br></strong>iframe跨域的方式,功能强于JSONP,它不仅能用来跨域完成HTTP请求,还能在前端跨域实现JavaScript调用。因此,完全不同域的跨域问题,通常采用iframe的方式来解决。<br><br>与JSONP技术通过创建<script>节点向不同的域提交GET请求的工作方式类似,我们也可以通过在http://example1.com/index.php页面中创建指向http://example2.com/getinfo.php的iframe节点跨域提交GET请求。然而,请求返回的结果无法回调http://example1.com/index.php页面中的callback函数,因为受到“同源策略”的影响。<br><br>为了解决这个问题,我们需要在example1.com下放置一个跨域文件,比如路径是http://example1.com/crossdomain.html。<br><br>当http://example2.com/getinfo.php这个请求返回结果的时候,它大体上有两个选择。<br>第一个选择是,它可以在iframe中做一个302跳转,跳转到跨域文件http://example1.com/crossdomain.html,同时将返回结果经过URL编码之后作为参数缀在跨域文件URL后面,例如http://example1.com/crossdomain.html?result=<URL-Encoding-Content>。<br><br>另一个选择是,它可以在返回的页面中再嵌入一个iframe,指向跨域文件,同时也是将返回结果经过URL编码之后作为参数缀在跨域文件URL后面。<br><br>在跨域文件中,包含一段JavaScript代码,这段代码完成的功能,是从URL中提取结果参数,经过一定处理后调用原来的http://example1.com/index.php页面中的一个预先约定好的callback函数,同时将结果参数传给这个函数。http://example1.com/index.php页面和跨域文件是在同一个域下的,因此这个函数调用可以通过。跨域文件所在iframe和原来的http://example1.com/index.php页面的关系,在前述第一种选择下,后者是前者的父窗口,在第二种选择下,后者是前者的父窗口的父窗口。<br><br>根据前面的叙述,有了跨域文件之后,我们就可以实现通过iframe方式在不同域之间进行JavaScript调用。这个调用过程可以完全跟HTTP请求无关,例如有些站点可以支持动态地调整在页面中嵌入的第三方iframe的高度,这其实是通过在第三方iframe里面检测自己页面的高度变化,然后通过跨域方式的函数调用将这个变化告知父窗口来完成的。<br><br>既然利用iframe可以实现跨域JavaScript调用,那么跨域提交POST请求等其它类型的HTTP请求就不是难事。例如我们可以跨域调用目标域的JavaScript代码在目标域下提交Ajax请求(GET/POST/etc.),然后将返回的结果再跨域传原来的域。<br><br>使用iframe跨域,优点是功能强大,支持各种浏览器,几乎可以完成任何跨域想做的事情;缺点是实现复杂,要处理很多浏览器兼容问题,并且传输的数据不宜过大,过大了可能会超过浏览器对URL长度的限制,要考虑对数据进行分段传输等。</p> <p><strong>3. 利用flash实现跨域HTTP请求<br></strong><br>据称,flash在浏览器中的普及率高达90%以上。<br><br>flash代码和JavaScript代码之间可以互相调用,并且flash的“安全沙箱”机制与JavaScript的安全机制并不尽相同,因此,我们可以利用flash来实现跨域提交HTTP请求(支持GET/POST等)。<br>例如,我们用浏览器访问http://example1.com/index.php这个页面,在这个页面中引用了http://example2.com/flash.swf这个flash文件,然后在flash代码中向http://example3.com/webservice.php发送HTTP请求。<br><br>这个请求能否被成功发送,取决于在example3.com的根路径下是否放置了一个crossdomain.xml以及这个crossdomain.xml的配置如何。flash的“安全沙箱”会保证:仅当example3.com服务器在根路径下确实放置了crossdomain.xml文件并且在这个文件中配置了允许接受来自example2.com的flash的请求时,这个请求才能真正成功。下面是一个crossdomain.xml文件内容的例子:</p> <p></p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="91153" class="copybut" id="copybut91153" onclick="doCopy('code91153')"><u>Copy code</u></a></span> The code is as follows:</div> <div class="codebody" id="code91153"> <br><?xml version="1.0"?> <br><cross-domain-policy><br>  <allow-access-from domain="example2.com" /><br></cross-domain-policy><br> </div> <p><strong>4. window.postMessage<br></strong> window.postMessage is a new feature supported by HTML5, the next version of the HTML standard. Affected by the rapid advancement of current Internet technology, the demand for browser cross-domain communication is getting stronger and stronger, and the HTML standard finally takes cross-domain communication into consideration. But currently HTML5 is still just a draft. <br> window.postMessage is a safe method to implement direct cross-domain communication. However, not all browsers currently support it. Only Firefox 3, Safari 4 and IE8 can support this call. <br><br>The calling method to use it to send messages to other windows is roughly as follows:<br></p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="66586" class="copybut" id="copybut66586" onclick="doCopy('code66586')"><u>Copy the code</u></a></span> The code is as follows:</div> <div class="codebody" id="code66586">otherWindow.postMessage(message, targetOrigin);</div> <br>In the receiving window, you need to set up an event processing function to receive the sent message: <br><div class="codetitle"> <span><a style="CURSOR: pointer" data="40287" class="copybut" id="copybut40287" onclick="doCopy('code40287')"><u>Copy code</u></a></span> The code is as follows:</div> <div class="codebody" id="code40287">window.addEventListener("message", receiveMessage, false);<br>function receiveMessage(event) {<br> if (event .origin !== "http://example.org:8080") return;<br>}</div> <br>The message contains three attributes: data, origin (carrying the real information of the domain where the sending window is located) and source (Representing the handle of the sending window). <br><br>Security considerations: When using window.postMessage, you must use the origin and source attributes of the message to verify the identity of the sender, otherwise XSS vulnerabilities will occur. <br><br>window.postMessage is as powerful as the cross-domain function implemented by iframe, and is simple to use and more efficient. However, the disadvantage is that it currently needs to be improved in terms of browser compatibility. <br><br>What needs to be added to the original text is that under IE6 and IE7, the vulnerability of IE's Opener that can be assigned to Object or Function can be exploited, and a supplementary solution for the postMessage solution is provided: <br>Main page: <p></p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="92626" class="copybut" id="copybut92626" onclick="doCopy('code92626')"><u>Copy code</u></a></span> The code is as follows:</div> <div class="codebody" id="code92626"> <br><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br><html xmlns="http://www.w3.org/1999/xhtml"><br><head><br>    <title>CrossDomain</title><br></head><br><body><br>    <iframe src="http://sh-tanzhenlin/CrossDomain-child.html"<BR>        frameborder="0" visible="false" height="0" width="0" id="ifrChild"></iframe><br><br>    <script type="text/javascript"><br>        var child = document.getElementById("ifrChild");<br>        var openerObject = {<br>                funcInParent:function(arg){<br>                    alert(arg);<br>                    alert('executed by a function in parent page');<br>                }<br>            }<br><br>        if(! 'v1' && !'1'[0]){ //test browser is ie6 or ie7   <br>            //crack<br>            child.contentWindow.opener = openerObject;<br>        }<br>        else{<br>            //postMessage showtime<br>        }<br><br>        function onClick(){<br>            //debugger;<br>            openerObject.funcInIframe('data from parent page ');<br>        }<br>    </script>
   


用iframe内嵌其它域下的页面:

复制代码 代码如下:





              
       
       
       

注:postMessage方式正以意想不到的速度得到各种新浏览器的支持,应予以着重考虑。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:Two methods of deep copy and shallow copy of JavaScript array_javascript skillsNext article:Two methods of deep copy and shallow copy of JavaScript array_javascript skills

Related articles

See more