Heim > Artikel > Web-Frontend > Eingehende Analyse domänenübergreifender Javascript-Probleme_Javascript-Fähigkeiten
Was ist domänenübergreifend?
Angenommen, a.com/get.html muss die Daten in b.com/data.html abrufen, und a.com und b.com sind nicht derselbe Server. Dies ist ein domänenübergreifender Server mit Javascript. Einfach ausgedrückt besteht die Same-Origin-Richtlinie darin, die Sicherheit der Website zu schützen und zu verhindern, dass der Inhalt der Website durch js von externen Domänenservern (nicht mit demselben Ursprung) geändert wird.
Zitieren Sie eine Tabelle, um zu sehen, welche Bedingungen zu gegenseitigen Ursachen führen:
Aber manchmal müssen wir das wirklich tun. Welche Methoden haben wir also?
1. JsonP
Wenn es um domänenübergreifendes Arbeiten geht, dürfen wir nicht umhin, zuerst JSONP zu erwähnen. JSONP ist eigentlich die Abkürzung für JavacScript Object Notation with Padding, die als mit Inhalt gefüllte Daten im JSON-Format verstanden werden kann.
Da der Rückruf oben deklariert ist und die data.js der externen Domäne b.com aufgerufen wird, heißt die data.js:
callback({msg:"tqtan"});
Auf diese Weise wird beim Aufruf von js, das auf die externe Domäne verweist, der lokale Rückruf () aufgerufen, um eine Datenübertragung zu erreichen.
Das Obige ist nur eine einfache domänenübergreifende Methode. Schauen wir uns die tatsächliche Anwendung von jQuery an.
Ajax in jQuery kann Daten aus externen Domänen über zwei Methoden abrufen:
1. $.getJSON()
Diese Methode ist einfach und grob und fordert Json von der externen Domäne an.
Angenommen, die obige Anforderung greift auf die Servlet-Seite unter b.com zu und der übergebene Parameter ist callback=?, dann generiert jQuery automatisch eine Zeichenfolge zum Ausfüllen des Platzhalters?, zum Beispiel callback=jQuery17207481773362960666_1332575486681. Dadurch wird eine eindeutige Kennung beim Server deklariert. Der Server muss nur Daten im JSON-Format mit diesem Rückrufwert zurückgeben, zum Beispiel:
Auf diese Weise können Sie erfolgreich Daten von Servern mit unterschiedlichem Ursprung abrufen.
2. $.ajax()
Das Implementierungsprinzip ist das gleiche wie oben, außer dass weitere Links angepasst werden können.
$.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); } });
Der Name des Rückrufs kann angepasst werden, hier wird er in „tqtan“ geändert und der Wert „words=hi“ kann hier übergeben werden.
Beachten Sie, dass das JsonP-Format nur im GET-Format beim Server angefordert werden kann.
2. document.domain
Diese Methode gilt nur für Cross-Domains, bei denen die Hauptdomain dieselbe ist, die Subdomains jedoch unterschiedlich sind.
Das ist das domänenübergreifende Problem zwischen get.a.com und data.a.com. Die Lösung ist ganz einfach:
Wenn get.a.com/get.html die Daten von data.a.com/data.html abrufen muss, fügen Sie zuerst einen Iframe in get.html ein, src zeigt auf data.a.com/data.html und dann in data.html Schreiben Sie document.domain='a.com';, um den Inhalt in data.html zu steuern.
//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. URL-Hash
Sie können auch domänenübergreifend durch URL-Hash erreichen. Hash ist der Inhalt nach URL#, wie zum Beispiel http://targetkiller.net/index.html#data, wobei #data der Hash ist. Wie kann man dies nutzen, um domänenübergreifend zu erreichen?
Immer noch das gleiche Beispiel: a.com/get.html muss b.com/data.html abrufen, zuerst einen Iframe in get.html erstellen, src zeigt immer noch auf data.html und dann den Hash-Wert hinzufügen Übergeben Sie die Parameter. Data.html am anderen Ende antwortet basierend auf dem erhaltenen Hash, erstellt selbst einen Iframe, src zeigt auf a.com/proxy.html und fügt die Antwortdaten dem Hash hinzu. Danach muss a.com/proxy.html nur noch den Hash von get.html in derselben übergeordneten Domäne von a.com ändern. Wie erhält man schließlich die Daten? Sie müssen lediglich einen Timer setInterval in get.html schreiben und überwachen, ob regelmäßig neue Hashes vorhanden sind.
Wenn Sie das sehen, sind Sie vielleicht verwirrt. Hier ein paar Fragen:
1. Welche Rolle spielt Proxy.html?
Da sich get.html und data.html nicht in derselben Domäne befinden, kann der Wert von location.hash nicht geändert werden. Springen Sie daher mit Proxy.html zuerst zur Seite, um einen Proxy zu finden, und verwenden Sie dann parent.location.hash Das heißt, den Vater so zu ändern, dass der Sohn (get.html) ebenfalls eine Antwort erhält.
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。