Maison >interface Web >js tutoriel >Analyse approfondie des problèmes inter-domaines Javascript_compétences Javascript
Qu'est-ce que le cross-domain ?
Supposons que a.com/get.html doive obtenir les données dans b.com/data.html et que a.com et b.com ne soient pas le même serveur. Il s'agit d'un inter-domaine impliquant Javascript. La politique de même origine, en termes simples, consiste à protéger la sécurité du site Web et à empêcher que le contenu du site Web ne soit modifié par js à partir de serveurs de domaine externes (de même origine).
Citez un tableau pour voir quelles sont les conditions qui provoquent des causes croisées :
Mais parfois, nous avons vraiment besoin de le faire, alors de quelles méthodes disposons-nous ?
1.JsonP
En matière de cross-domain, nous ne pouvons manquer de mentionner jsonp en premier. jsonp est en fait l'abréviation de JavacScript Object Notation with Padding, qui peut être comprise comme des données au format json remplies de contenu.
Parce que le rappel est déclaré ci-dessus et que le data.js du domaine externe b.com est appelé, et le data.js est appelé :
rappel({msg:"tqtan"});
De cette façon, lors de l'appel de js qui fait référence au domaine externe, le callback local() sera appelé pour réaliser la transmission des données.
Ce qui précède n'est qu'un simple inter-domaine, regardons l'application réelle de jQuery.
Ajax dans jQuery peut extraire des données de domaines externes via deux méthodes :
1. $.getJSON()
Cette méthode est simple et grossière, demandant Json au domaine externe.
Supposons que la requête ci-dessus accède à la page du servlet sous b.com et que le paramètre transmis est callback=?, jQuery générera automatiquement une chaîne pour remplir l'espace réservé ?, par exemple, callback=jQuery17207481773362960666_1332575486681. Ceci déclare un identifiant unique auprès du serveur. Le serveur n'a besoin que de renvoyer des données au format json avec cette valeur de rappel, par exemple :
De cette façon, vous pouvez obtenir avec succès des données provenant de serveurs d'origine différente.
2. $.ajax()
Le principe de mise en œuvre est le même que ci-dessus, sauf que davantage de liens peuvent être personnalisés.
$.ajax({ url:'http://b.com/dataServlet?words=hi', dataType:'jsonp', jsonp : 'jsoncallback', jsoncallback : 'tqtan', success:function(data){ console.log(data.msg); }, error: function (e) { console.log(e); } });
Le nom du rappel peut être personnalisé, ici il est changé en 'tqtan', et la valeur mots=hi peut être transmise ici.
Notez que le format JsonP ne peut être demandé au serveur qu'au format GET.
2. document.domaine
Cette méthode s'applique uniquement aux domaines croisés où le domaine principal est le même mais les sous-domaines sont différents.
C'est le problème inter-domaines entre get.a.com et data.a.com. La solution est très simple :
.
Si get.a.com/get.html doit obtenir les données de data.a.com/data.html, insérez d'abord une iframe dans get.html, src pointe vers data.a.com/data.html, puis dans data.html Écrivez document.domain='a.com'; pour contrôler le contenu dans data.html.
//get.html var iframe = document.creatElement("iframe"); iframe.src="http://data.a.com/data.html"; iframe.style.display="none"; document.body.appendChild(iframe); document.domain = 'a.com'; iframe.onload = function(){ var otherDocument = iframe.contentDocument || iframe.contentWindow.document; //otherDocument就是另一个页面的document //do whatever you want.. }; //data.html document.domain = 'a.com';
3. Hachage d'URL
Vous pouvez également réaliser des opérations inter-domaines via le hachage d'URL. Le hachage est le contenu après l'url#, tel que http://targetkiller.net/index.html#data, où #data est le hachage. Comment utiliser cela pour réaliser du cross-domain ?
Toujours le même exemple, a.com/get.html doit obtenir b.com/data.html, créez d'abord une iframe dans get.html, src pointe toujours vers data.html, puis ajoutez la valeur de hachage à passer les paramètres. Data.html à l'autre extrémité répond en fonction du hachage obtenu, crée lui-même une iframe, src pointe vers a.com/proxy.html et ajoute les données de réponse au hachage. Après cela, a.com/proxy.html n'a plus qu'à modifier le hachage de get.html dans le même domaine parent a.com. Finalement, comment obtenir les données ? Il vous suffit d'écrire un timer setInterval dans get.html et de surveiller régulièrement s'il y a de nouveaux hachages.
En voyant cela, vous pourriez vous sentir confus. Voici quelques questions :
1.Quel est le rôle de proxy.html ?
Puisque get.html et data.html ne sont pas dans le même domaine, la valeur location.hash ne peut pas être modifiée, donc en utilisant proxy.html, accédez d'abord à la page pour trouver un proxy, puis utilisez parent.location.hash, cela c'est-à-dire modifier le père pour permettre au fils (get.html) d'obtenir également une réponse.
a.com/get.html
var iframe = document.createElement('iframe'); iframe.src = 'http://a.com/get.html#data'; iframe.style.display = 'none'; document.body.appendChild(iframe); //周期检测hash更新 function getHash() { var data = location.hash ? location.hash.substring(1) : ''; console.log(data); } var hashInt = setInterval(function(){getHash()}, 1000); a.com/proxy.html parent.location.hash = self.location.hash.substring(1); b.com/data.html //模拟一个简单的参数处理操作 if(location.hash){ var data = location.hash; doSth(data); } function doSth(data){ console.log("from a.com:"+data); var msg = "hello i am b.com"; var iframe = document.createElement('iframe'); iframe.src = "http://a.com/proxy.html#"+msg; iframe.style.display = 'none'; document.body.appendChild(iframe); }
4、window.name
这种方法比较巧妙,引用圆心的解释,name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
具体例子依旧如上,同时也是需要一个代理页面。
a.com/get.html请求b.com/data.html,首先get.html创建一个iframe,src指向data.html,然后监听iframe的onload事件。与此同时,在data.html设置window.name = data;把window.name赋值。然后onload事件后马上把iframe的跳到本地a.com/proxy.html。因此window.name就共享到了src为proxy.html的找个iframe中,接下来,就是同源间获取值的事了。
a.com/get.html
var state = 0, iframe = document.createElement('iframe'), iframe.src = 'http://b.com/data.html"; iframe.style.display = 'none'; loadfn = function() { if (state === 1) { var data = iframe.contentWindow.name; console.log(data); } else if (state === 0) { state = 1; //跳到proxy.html iframe.contentWindow.location = "http://a.com/proxy.html"; } }; if (iframe.attachEvent) { iframe.attachEvent('onload', loadfn); } else { iframe.onload = loadfn; } document.body.appendChild(iframe); a.com/proxy.html // proxy.html的操作主要是删除get.html的iframe,避免安全问题发生 iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); b.com/data.html var data = "hello,tqtan"; window.name = data;
5、 postMessage()
html5的新方法postMessage()优雅地解决了跨域,也十分容易理解。
发送方调用postMessage()内容,接受方监听onmessage接受内容即可。
假设发送方为a.com/send.html,接受方为b.com/receive.html。
a.com/send.html
var iframe = document.createElement("iframe"); iframe.src = "http://b.com/receive.html"; document.body.appendChild(iframe); iframe.contentWindow.postMessage("hello","http://b.com"); b.com/receive.html window.addEventListener('message', function(event){ // 通过origin属性判断消息来源地址 if (event.origin == 'http://a.com') { console.log(event.data); console.log(event.source);//发送源的window值 } }, false);
6、CORS(后台实现)
以上5点都是前端实现的跨域,但是后台参与会让跨域更容易解决,也就是用CORS。
CORS是Cross-Origin Resource Sharing的简称,也就是跨域资源共享。它有多牛逼?之前说JsonP只能get请求,但CORS则可以接受所有类型的http请求,然而CORS只有现代浏览器才支持。
怎样使用?前端只需要发普通ajax请求,注意检测CORS的支持度。引用自蒋宇捷。
function createCORSRequest(method, url) { var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr) { // 此时即支持CORS的情况 // 检查XMLHttpRequest对象是否有“withCredentials”属性 // “withCredentials”仅存在于XMLHTTPRequest2对象里 xhr.open(method, url, true); } else if (typeof!= "undefined") { // 否则检查是否支持XDomainRequest,IE8和IE9支持 // XDomainRequest仅存在于IE中,是IE用于支持CORS请求的方式 xhr = new XDomainRequest(); xhr.open(method, url); } else { // 否则,浏览器不支持CORS xhr = null; } return xhr; } var xhr = createCORSRequest('GET', url); if (!xhr) { throw new Error('CORS not supported'); }
与此同时,服务器端只需要设置Access-Control-Allow-Origin头即可。
java中你只需要设置
为了安全,也可以将*改为特定域名,例如a.com。