先說定義,什么是跨域:
? ? 對(duì)于瀏覽器而言,只要訪問域名憔四、協(xié)議、端口中任何一個(gè)不同就會(huì)引發(fā)同源策略般眉。
? ? 同源策略就是為了保護(hù)用戶安全了赵,防止不同域JS交互:
? ? ? ?1限制cookie 、localStorage 甸赃、indexDB 的讀仁裂础;
? ? ? ? 2無(wú)法獲取DOM信息埠对;
? ? ? ? 3Ajax請(qǐng)求無(wú)法發(fā)送络断。
如何解決跨域問題
? ? 1.CORS (跨域資源共享) -- Cross-Origin-Resource-Sharing
? ? 原理:使用自定義的HTTP頭讓瀏覽器和服務(wù)器進(jìn)行溝通,來判斷請(qǐng)求或者相應(yīng)是否成功项玛;
? ? 所以只有在被請(qǐng)求的Reponse header 中加入如下設(shè)置即可實(shí)現(xiàn)跨域訪問:
? ? ”Access-Control-Allow-Origin:*“??//指定允許其他域名訪問
? ? "Access-Control-Allow-Methods:GET,POST"? //響應(yīng)類型
? ? ”Access-Control-Allow-Header:x-requested-with,content-type“ //響應(yīng)頭設(shè)置
? ? 2.通過Jsonp跨域 - Json with Padding(填充式j(luò)son)的簡(jiǎn)寫
????JSONP的原理:通過script標(biāo)簽引入一個(gè)js文件貌笨,這個(gè)js文件載入成功后會(huì)執(zhí)行我們?cè)趗rl參數(shù)中指定的函數(shù),并且會(huì)把我們需要的json數(shù)據(jù)作為參數(shù)傳入襟沮。所以jsonp是需要服務(wù)器端的頁(yè)面進(jìn)行相應(yīng)的配合的锥惋。(即用JavaScript動(dòng)態(tài)加載一個(gè)script文件昌腰,同時(shí)定義一個(gè)callback函數(shù)給script執(zhí)行而已。)
????在js中膀跌,我們直接用XMLHttpRequest請(qǐng)求不同域上的數(shù)據(jù)時(shí)遭商,是不可以的。但是捅伤,在頁(yè)面上引入不同域上的js腳本文件卻是可以的劫流,jsonp正是利用這個(gè)特性來實(shí)現(xiàn)的。
? ? 3.使用HTML5的window.postMessage方法跨域
? ? HTML5引入了一個(gè)新的API:跨文檔通信API(Cross-document-message)
? ? 這個(gè)API里有個(gè)叫window.postMessage方法暑认,看名字顯而易見了困介,允許瀏覽器跨窗口通信,不論這兩個(gè)窗口是否同源蘸际。很牛逼白ā!
? ? 例如:a.html 向 b.html 發(fā)送數(shù)據(jù)粮彤,調(diào)用postMessage方法:
????a頁(yè)面:
????```
? ? <iframe id="frame1" src="http://127.0.0.1/JSONP/b.html" frameborder="1"></iframe>
????document.getElementById('frame1').onload = function(){
? ? var win = document.getElementById('frame1').contentWindow;
? ? win.postMessage("我是來自a頁(yè)面的","http://127.0.0.1/JSONP/b.html")
????}
????```
? ? b頁(yè)面:
? ??```
? ??window.onmessage =function(e){
? ? e = e || event;
????console.log(e.data);//我是來自a頁(yè)面的
????}
????```
????子窗口向父窗口發(fā)送消息的寫法類似根穷。
? ? ```
????window.opener.postMessage('我是來自b頁(yè)面的','http://a.com');?//父窗口和子窗口都可以通過message事件,監(jiān)聽對(duì)方的消息导坟。
? ? ```
????通過window.postMessage屿良,讀寫其他窗口的 LocalStorage 也成為了可能。?
????下面是一個(gè)例子惫周,主窗口寫入iframe子窗口的localStorage尘惧。?
????父窗口發(fā)送消息代碼:
? ? ```
????var win = document.getElementsByTagName('iframe')[0].contentWindow;
????var obj = { name: 'Jack' };
????// 存入對(duì)象
????win.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://b.com');
????// 讀取對(duì)象
????win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
????window.onmessage = function(e) {
????? if (e.origin != 'http://a.com') return;
? ????// "Jack"
????? console.log(JSON.parse(e.data).name);
????};
?```
子窗口接收消息的代碼:
```
window.onmessage = function(e) {
? if (e.origin !== 'http://bbb.com') return;
? var payload = JSON.parse(e.data);
? switch (payload.method) {
? ? case 'set':
? ? ? localStorage.setItem(payload.key, JSON.stringify(payload.data));
? ? ? break;
? ? case 'get':
? ? ? var parent = window.parent;
? ? ? var data = localStorage.getItem(payload.key);
? ? ? parent.postMessage(data, 'http://aaa.com');
? ? ? break;
? ? case 'remove':
? ? ? localStorage.removeItem(payload.key);
? ? ? break;
? }
};
```