Maison >interface Web >js tutoriel >Introduction complète à deux technologies inter-domaines dans les compétences JavaScript_javascript

Introduction complète à deux technologies inter-domaines dans les compétences JavaScript_javascript

WBOY
WBOYoriginal
2016-05-16 16:52:101331parcourir

Cette politique impose des restrictions importantes sur le contenu de la page auquel le code JavaScript peut accéder, c'est-à-dire que JavaScript ne peut accéder qu'au contenu du même domaine que le document qui le contient.

La stratégie de sécurité JavaScript est particulièrement importante lors de la programmation multi-iframe ou multi-fenêtres, ainsi que de la programmation Ajax. Selon cette politique, le code JavaScript contenu dans les pages sous baidu.com ne peut pas accéder au contenu des pages sous le nom de domaine google.com ; même les pages situées entre différents sous-domaines ne peuvent pas accéder entre elles via le code JavaScript. L'impact sur Ajax est que les requêtes Ajax implémentées via XMLHttpRequest ne peuvent pas soumettre de requêtes à différents domaines. Par exemple, les pages sous abc.example.com ne peuvent pas soumettre de requêtes Ajax à def.example.com, etc.

Cependant, lors de la programmation frontale approfondie, des opérations inter-domaines sont inévitablement nécessaires. À l'heure actuelle, la « même politique d'origine » semble trop stricte. Cet article résume certaines technologies requises pour le cross-domain sur cette question.

Ci-dessous, nous discutons de la technologie inter-domaines dans deux situations : d'abord, nous discutons de la technologie inter-domaines dans différents sous-domaines, puis nous discutons de la technologie inter-domaines dans des domaines complètement différents.

(1) Technologies inter-domaines dans différents sous-domaines.

Nous aborderons deux questions séparément : la première question est de savoir comment effectuer des appels JavaScript sur différents sous-domaines ; la deuxième question est de savoir comment soumettre des requêtes Ajax à différents sous-domaines.

Résolvons d'abord le premier problème. Supposons qu'il y ait deux sous-domaines différents sous le domaine example.com : abc.example.com et def.example.com. Supposons maintenant qu'il y ait une page sous def.example.com, qui définit une fonction JavaScript :

Copier le code Le code est le suivant suit :
function funcInDef() {
.....
}

Nous voulons appeler la fonction ci-dessus dans une page sous abc.example.com. Supposons que la page sous abc.example.com dont nous voulons discuter soit intégrée dans la page sous def.example.com sous la forme d'une iframe. Dans ce cas, nous pouvons essayer de faire l'appel suivant dans l'iframe :

Copier le code Le code est le suivant :
window.top.funcInDef();
D'accord, nous avons remarqué que cet appel est interdit par la "même politique d'origine" mentionnée précédemment, et le moteur JavaScript lèvera directement une exception.
Afin de mettre en œuvre l'appel ci-dessus, nous pouvons le faire en modifiant les attributs de domaine des deux pages. Par exemple, nous pouvons ajouter les extraits de code JavaScript suivants en haut des deux pages au-dessus de abc.example.com et def.example.com :

Copier le codeLe code est le suivant :
document.domain = "example.com";
De cette façon, les deux pages deviennent le même domaine et les appels précédents peuvent être exécutés normalement.


Une chose à noter ici est que l'attribut document.domain d'une page ne peut être défini que sur un nom de domaine de niveau supérieur (à l'exception du nom de domaine de premier niveau), mais ne peut pas être défini sur un sous-domaine. plus profond que le nom de domaine actuel. Par exemple, la page abc.example.com ne peut définir son domaine que sur example.com, pas sub.abc.example.com, et bien sûr, elle ne peut pas être définie sur le nom de domaine de premier niveau com.

L'exemple ci-dessus traite du cas où deux pages appartiennent à une relation imbriquée iframe Lorsque les deux pages ont une relation ouverte et ouverte, le principe est exactement le même.

Résolvons le deuxième problème : comment soumettre des requêtes Ajax à différents sous-domaines.
Normalement, nous utiliserons un code similaire au suivant pour créer un objet XMLHttpRequest :

Copier le code Le code est le suivant :
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; usines.length; i ) {
essayer {
var usine = usines[i];
return usine();
} catch(e) {}
}
renvoie null ;
>

Le code ci-dessus fait référence à ActiveXObject pour la compatibilité avec les navigateurs de la série IE6. Chaque fois que nous appelons la fonction newRequest, nous obtenons un objet Ajax nouvellement créé, puis utilisons cet objet Ajax pour envoyer une requête HTTP. Par exemple, le code suivant envoie une requête GET à abc.example.com :
Copiez le code Le code est le suivant :

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

En supposant que le code ci-dessus soit inclus dans une page sous le nom de domaine abc.example.com, la requête GET peut être envoyée avec succès sans aucun problème. Cependant, si nous envoyons maintenant une requête à def.example.com, un problème inter-domaines se produit et le moteur JavaScript lève une exception.
La solution est de placer un fichier inter-domaine sous le domaine def.example.com, en supposant qu'il s'appelle crossdomain.html puis de déplacer la définition de la fonction newRequest précédente vers ce fichier inter-domaine ; document comme avant. La valeur du domaine est la même. En haut du fichier crossdomain.html et de la page qui appelle Ajax sous le domaine abc.example.com, ajoutez :

Copier le code Le code est le suivant :
document.domain = "example.com";


Afin d'utiliser cross- fichiers de domaine, nous appelons Ajax sous le domaine abc.example.com. Intégrez une iframe cachée pointant vers un fichier inter-domaines dans la page, par exemple :
Copiez le code Le code est le suivant :


À l'heure actuelle, la page sous le domaine abc.example.com et le fichier inter-domaines crossdomain.html sont tous deux sous le même domaine (example.com). Nous pouvons appeler crossdomain.html dans la page sous le domaine abc.example.com. La fonction newRequest dans :
Copier le code . Le code est le suivant :
var request = window.frames["xd_iframe" ].newRequest();

L'objet requête ainsi obtenu peut envoyer un Requête HTTP à http://def.example.com.

(2) Technologies inter-domaines dans des domaines complètement différents.

Si les noms de domaine de premier niveau sont différents, par exemple, example1.com et example2.com souhaitent communiquer sur le front-end via JavaScript, la technologie requise est plus compliquée.

Avant d'expliquer la technologie inter-domaines de différents domaines, précisons d'abord que la technologie discutée ci-dessous est également applicable à la situation précédente dans différents sous-domaines, car le croisement de différents sous-domaines est seulement un cas particulier de problèmes inter-domaines. Bien entendu, l’utilisation de la bonne technologie dans les bonnes circonstances peut garantir une meilleure efficacité et une plus grande stabilité.

En bref, selon les différentes exigences inter-domaines, les technologies inter-domaines peuvent être classées dans les catégories suivantes :
1. Requête GET inter-domaines JSONP
2. iframe
3. Requête HTTP inter-domaines Flash
4. window.postMessage
Diverses technologies sont présentées en détail ci-dessous.
1.JSONP.
La méthode de soumission de requêtes HTTP à différents domaines en créant des nœuds <script> dans la page est appelée JSONP. Cette technologie peut résoudre le problème de la soumission de requêtes Ajax entre domaines. Le principe de fonctionnement de JSONP est le suivant : <br> En supposant qu'une requête GET soit soumise à http://example2.com/getinfo.php dans la page http://example1.com/index.php, on peut mettre le code JavaScript suivant Placez-le dans la page http://example1.com/index.php à implémenter : <br></p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="91817" class="copybut" id="copybut91817" onclick="doCopy('code91817')"><u>Copiez le code</u></a></span> Le le code est le suivant :</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>Copier le code</u></a></span> Le code est le suivant :</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 est une nouvelle fonctionnalité supportée par HTML5, la prochaine version du standard HTML. Affectée par les progrès rapides de la technologie Internet actuelle, la demande de communication entre domaines du navigateur devient de plus en plus forte, et la norme HTML prend enfin en compte la communication entre domaines. Mais actuellement, HTML5 n’est encore qu’un brouillon. <br> window.postMessage est une méthode sûre pour établir une communication directe entre domaines. Cependant, tous les navigateurs ne le prennent actuellement pas en charge. Seuls Firefox 3, Safari 4 et IE8 peuvent prendre en charge cet appel. <br><br>La méthode d'appel pour l'utiliser pour envoyer des messages à d'autres fenêtres est à peu près la suivante :<br></p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="66586" class="copybut" id="copybut66586" onclick="doCopy('code66586')"><u>Copiez le code</u></a></span> Le code est le suivant :</div> <div class="codebody" id="code66586">otherWindow.postMessage(message, targetOrigin);</div> <br>Dans la fenêtre de réception, vous devez mettre en place une fonction de traitement d'événements pour recevoir le message envoyé : <br> <div class="codetitle"> <span><a style="CURSOR: pointer" data="40287" class="copybut" id="copybut40287" onclick="doCopy('code40287')"><u>Copier le code</u></a></span> Le code est le suivant :</div> <div class="codebody" id="code40287">window.addEventListener("message", recevoirMessage, false);<br>function containMessage(event) {<br> if (event .origin !== "http://example.org:8080") return;<br>}</div> <br>Le message contient trois attributs : data, origin (portant les informations réelles du domaine où se trouve la fenêtre d'envoi) et source (représentant le handle de la fenêtre d'envoi). <br><br>Considérations de sécurité : lors de l'utilisation de window.postMessage, vous devez utiliser les attributs d'origine et de source du message pour vérifier l'identité de l'expéditeur, sinon des vulnérabilités XSS se produiront. <br><br>window.postMessage est aussi puissant que la fonction cross-domain implémentée par iframe, et est simple à utiliser et plus efficace. Cependant, l'inconvénient est qu'il doit actuellement être amélioré en termes de compatibilité avec les navigateurs. <br><br>Ce qu'il faut ajouter au texte original, c'est que sous IE6 et IE7, la vulnérabilité de l'Opener d'IE qui peut être affectée à un objet ou une fonction peut être exploitée, et une solution supplémentaire pour la solution postMessage est fournie : <br>Page principale : <p></p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="92626" class="copybut" id="copybut92626" onclick="doCopy('code92626')"><u>Copier le code</u></a></span> Le code est le suivant :</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>&lt ;/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('exécuté par une fonction dans la page parent' );<br>                }<br> }<br><br>        if(! 'v1' && !'1'[0]){ //le navigateur de test est ie6 ou ie7   <br>            //crack<br>            child.contentWindow.opener = openerObject;<br>>   openerObject.funcInIframe('données de la page parent') ;<br>        }<br>    </script>
   





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



复制代码



代码如下 :