Cross-domain communication example using iframe in js

Source: Internet
Author: User
To demonstrate the cross-origin effect, add the following content to the hosts file:
127.0.0.1 www.myapp.com 127.0.0.1 sample.myapp.com 127.0.0.1 www.otherapp.com
Next we will discuss how to use iframe for cross-origin communication. Here we will mainly introduce the following solutions: Document. domain, URL. hash, Cross-fragment, Window. name, PostMessage.
Document. domain
If source A and source B have the same parent domain name Document. domainAttribute, it is easy to make them communicate with each other. In the HTML specification Document. domainIs a read-only attribute. Modern browsers allow you to set it as a parent domain name (not a top-level domain name ). For example, Www.myapp.comPage, which can be set Myapp.comAnd the other from Sample.myapp.comPage can also be set Myapp.com, The following figure shows Document. domainWorking principle:
By Document. domainThe attribute is set to the same parent domain name to implement cross-domain communication between different subdomains. This is not within the scope of same-source policy restrictions. However, strictly speaking, the sub-domain Cross-Origin solution is most suitable for cross-origin communication between internal applications.

The example here is slightly different from the one mentioned above. The code on the homepage is as follows:


<! -- Http://www.myapp.com: 3000/demo1 -->
<Button> Test </button>
<Div> </div>
<Iframe id = "ifr" src = "http://sample.myapp.com: 3000/demo1-iframe"> </iframe>
<Script>
Document. domain = 'myapp. Com ';
Function sayHello (str ){
Document. querySelector ('div '). innerHTML = str;
}

Document. querySelector ('Button '). onclick = function (){
Document. querySelector ('# ifr'). contentWindow. sayHello ('Hello son ');
}
</Script>

The iframe page is as follows:

<! -- Http://sample.myapp.com: 3000/demo1-iframe -->
<Div> </div>
<Script>
Document. domain = 'myapp. Com ';
Function sayHello (str ){
Document. querySelector ('div '). innerHTML = str;
Parent. sayHello ('Hello father ');
}
</Script>

Set both the parent page and iframeDocument. domainIsMyapp.comWhen the button is clicked on the parent page, callSayHelloMETHOD. The child page also callsSayHelloMethod. The effect is as follows:

URL. hash
A url consists of the following parts:
In general, any changes to the URL will reload a new webpage, Hash, HashAny changes will not cause page refresh. HashIt has been widely used in SPA applications that support partial refresh to record users' access paths. In the cross-origin solution, HashIt is also very useful. Pages from different sources can set URLs for each other, including HashValue. HashValue. You can use HashTo communicate with each other. Example:
First look at the home page code


<! -- Http://www.myapp.com: 3000/demo2 -->
<Button> Send a message </button>
<Iframe id = "ifr" src = "http://www.otherapp.com: 3000/demo2-b"> </iframe>
<Script>
Var target = "http://www.otherapp.com: 3000/demo2-b ";
Function sendMsg (msg ){
Var data = {msg: msg };
Var src = target + "#" + JSON. stringify (data );
Document. getElementById ('ifr'). src = src;
}

Document. querySelector ('Button '). onclick = function (){
SendMsg ("time:" + (new Date ()));
}
</Script>
The iframe code is as follows:

<! -- Http://www.myapp.com: 3000/demo2-b -->
<Div> </div>
<Script>
Var oldHash = "";
Var target = "http://www.myapp.com: 3000/demo2 ";
CheckMessage = function (){
Var newHash = window. location. hash;
If (newHash. length> 1 ){
NewHash = newHash. substring (1, newHash. length );
If (newHash! = OldHash ){
OldHash = newHash;
Var msgs = JSON. parse (newHash );
Var msg = msgs. msg;
SendMessage ("Hello father ");
Document. querySelector ('div '). innerHTML = msg;
         }
     }
}
Window. setInterval (checkMessage, 1000 );
Function sendMessage (msg ){
Var hash = "msg =" + msg;
Parent. location. href = target + "#" + hash;
}
</Script>
The iframe-oriented transmission parameter on the home page changes the hash value of the iframe, and the iframe continuously obtains its own hash value. Once a change occurs, the message sent from the home page is displayed immediately, in addition, by setting the hash on the home page, you can transmit messages on the home page, so that two-way cross-origin traffic can be completed. The effect is as follows:

 

Cross-fragment
Because many websites HashHas been used for other purposes, for such websites HashCross-Origin will be very complex (from HashTo merge and separate messages ). Therefore, we have HashAn upgraded version: Cross-fragmentThe principle is shown in the following figure:

This scheme is essentially the same as the previous one, and is based on URLs.HashTo pass parameters, but a proxy page for the same domain is required to complete cross-origin. First look at the home page code:


<! -- Http://www.myapp.com: 3000/demo3 -->
<Button> Send a message </button>
<Div> </div>
<Iframe name = "otherapp" id = "otherapp" src = "http://www.otherapp.com: 3000/demo3-b"> </iframe>
<Script>
Function sendMsg (msg ){
Var frame = document. createElement ("frame ");
Var baseProxy = "http://www.otherapp.com: 3000/demo3-req-proxy ";
Var request = {frameName: "otherapp", data: msg };
Frame. src = baseProxy + "#" + encodeURI (JSON. stringify (request ));
Frame. style. display = "none ";
Document. body. appendChild (frame );
}
// Response processing function
Function getResponse (data ){
Document. querySelector ('div '). innerHTML = "received calculation result:" + data;
}
Document. querySelector ('Button '). onclick = function (){
SendMsg (Math. random ());
Return false;
}
</Script>
Request proxy page:

// Http://www.otherapp.com: 3000/demo3-req-proxy
Var hash = window. location. hash;
If (hash & hash. length> 1 ){
Var request = hash. substring (1, hash. length );
Var obj = JSON. parse (decodeURI (request ));
Var data = obj. data;
// Process data
Parent. frames [obj. frameName]. getData (data); // The getData method of the target page
 }
Target page:

<! -- Http://www.otherapp.com: 3000/demo3-b -->
<Div> </div>
<Script>
Function getData (data ){
Document. querySelector ('div '). innerHTML = "received parameter:" + data;
Var frame = document. createElement ("frame ");
Var baseProxy = "http://www.myapp.com: 3000/demo3-res-proxy ";
// Simply multiply the data by 100
Var request = {data: data * 100 };
Frame. src = baseProxy + "#" + encodeURI (JSON. stringify (request ));
Frame. style. display = "none ";
Document. body. appendChild (frame );
}
</Script>
Response proxy page:

// Http://www.myapp.com: 3000/demo3-res-proxy
Var hash = window. location. hash;
If (hash & hash. length> 1 ){
Var request = hash. substring (1, hash. length );
Var obj = JSON. parse (decodeURI (request ));
Var data = obj. data;
// Process data
Parent. parent. getResponse (data); // getResponse method on the home page
 }
In this example, first place an iframe (target page) under the otherapp on the home page (from myapp ), click the button to construct a hidden iframe (same as the target page, from the otherapp, request proxy page) on the home page, and call the getData method on the target page through this request proxy page, this method receives the incoming data. After processing, construct a hidden iframe (same as the domain on the home page, from myapp, response proxy page ), call the getResponse method on the home page on the response proxy page. The effect is as follows:


This method can be used to implement iframe cross-origin adaptive (see the example)
Window. name
Window. nameCross-Origin is a clever solution. Generally, we use Window. nameIs as follows:
  • UseWindow. frames [windowName]Obtain a subwindow.
  • Set it as the link elementTargetAttribute
Load any page Window. nameThe value remains unchanged. Because Window. nameThis notable feature makes it suitable for cross-origin communication between different origins, but this is an uncommon attribute. So how can we use the same-origin policy? The following figure shows how to use Window. name.

When Page A wants to obtain resources or Web services from another source, it first creates A hiddenIframeB. Point B to an external resource or service. After B is loaded, it attaches the response dataWindow. name. Since A and B are different from each other, A still cannot obtain B'sNameAttribute. After B obtains the data, it will navigate to any page with the same source as A. Then A can directly obtain B'sNameAttribute value. After A obtains the data, B can be deleted at any time.

Homepage code:

// Http://www.myapp.com: 3000/demo4
Function sendMsg (msg ){
Var state = 0, data;
Var frame = document. createElement ("frame ");
Var baseProxy = "http://www.otherapp.com: 3000/demo4-req ";
Var request = {data: msg };
Frame. src = baseProxy + "#" + encodeURI (JSON. stringify (request ));
Frame. style. display = "none ";
Frame. onload = function (){
If (state = 1 ){
Data = frame. contentWindow. name;
Document. querySelector ('. Res'). innerHTML = "get response:" + data;
// Delete iframe
Frame.contentdomaindoc ument. write ('');
Frame. contentWindow. close ();
Document. body. removeChild (frame );
} Else {
State = 1;
Frame. src = "http://www.myapp.com: 3000/demo4-res ";
      }
};
Document. body. appendChild (frame );
}

Document. querySelector ('Button '). onclick = function (){
Var val = Math. random ();
SendMsg (val );
Document. querySelector ('. VAL'). innerHTML = "request data:" + val;
}
Target page code:

// Http://www.otherapp.com: 3000/demo4-res
Var hash = window. location. hash;
If (hash & hash. length> 1 ){
Var request = hash. substring (1, hash. length );
Var obj = JSON. parse (decodeURI (request ));
Var data = obj. data;
// Multiply data by 100
Window. name = data * 100;
}
In this example, the requested data is placed in the hash to input the target page of other domains. The target page will multiply the data by 100 and then set it to window. name, and then jump to the page with the same domain as the home page, so that the home page can be from the window. name. The effect is as follows:

 

PostMessage
New methods in HTML5 specifications Window. postMessage (message, targetOrigin)It can be used for secure cross-origin communication. When this method is called, a message event is distributed. If the window listens to the corresponding message, the window can get the message and message source. As shown in the following figure:
If iframe wants to notify the parent window of different sources that it has been loaded, you can use Window. postMessageTo send messages. At the same time, it will listen to the feedback message:

 


// Http://www.otherapp.com: 3000/demo5-b
Function postMessage (msg ){
Var targetWindow = parent. window;
TargetWindow. postMessage (msg ,"*");
}
Function handleReceive (msg ){
If (msg. data = "OK "){
// The task to be done is here
} Else {
// Resend the message
PostMessage (JSON. stringify ({color: 'red '}));
 }
}
Window. addEventListener ("message", handleReceive, false );
Window. onload = function (){
PostMessage (JSON. stringify ({color: 'red '}));
}
The parent window listens to message events. When a message arrives, it first checks whether the message is sent at www.otherapp.com. If yes, it sends a feedback message.

// Http://www.myapp.com: 3000/demo5
Function handleReceive (event ){
If (event. origin! = "Http://www.otherapp.com: 3000") return;
// Process data
Var data = JSON. parse (event. data );
Document. querySelector ('div '). innerHTML = "color from iframe:" + data. color;

Var otherAppFrame = window. frames ["otherApp"]
OtherAppFrame. postMessage ("OK", "http://www.otherapp.com: 3000 ");
}
Window. addEventListener ("message", handleReceive, false );
So far, all cross-origin communication ends here. If you have any good solutions, please leave a message.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.