To demonstrate the cross-origin effect, add the following content to the hosts file:
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.
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:
- Use
Window. frames [windowName]Obtain a subwindow.
- Set it as the link element
TargetAttribute
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.