什么是跨域
跨域,指的是瀏覽器不能執(zhí)行其他網(wǎng)站的腳本,就是跨域名,跨端口,跨協(xié)議。它是由瀏覽器的同源策略造成的,是瀏覽器施加的安全限制。
跨域的幾種方法
JSONP
html中script標(biāo)簽可以引入其他域下的js,比如引入線上的jquery庫(kù)。利用這個(gè)特性,可實(shí)現(xiàn)跨域訪問(wèn)接口。需要后端支持
echo $cb . '&&' . $cb . '(' . json_encode($ret) . ')';
- 定義數(shù)據(jù)處理函數(shù)_fun
- 創(chuàng)建script標(biāo)簽,src的地址執(zhí)行后端接口,最后加個(gè)參數(shù)callback=_fun
- 服務(wù)端在收到請(qǐng)求后,解析參數(shù),計(jì)算返還數(shù)據(jù),輸出 fun(data) 字符串。
- fun(data)會(huì)放到script標(biāo)簽做為js執(zhí)行。此時(shí)會(huì)調(diào)用fun函數(shù),將data做為參數(shù)。
1)代碼:
function handleResponse(response){
console.log('The responsed data is: '+response.data);
}
var script = document.createElement('script');
script.src = 'http://www.baidu.com/json/?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);
/*handleResonse({"data": "zhe"})*/
//原理如下:
//當(dāng)我們通過(guò)script標(biāo)簽請(qǐng)求時(shí)
//后臺(tái)就會(huì)根據(jù)相應(yīng)的參數(shù)(json,handleResponse)
//來(lái)生成相應(yīng)的json數(shù)據(jù)(handleResponse({"data": "zhe"}))
//最后這個(gè)返回的json數(shù)據(jù)(代碼)就會(huì)被放在當(dāng)前js文件中被執(zhí)行
//至此跨域通信完成
CORS
CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing),是一種 ajax 跨域請(qǐng)求資源的方式,支持現(xiàn)代瀏覽器,IE支持10以上。 實(shí)現(xiàn)方式很簡(jiǎn)單,當(dāng)你使用 XMLHttpRequest 發(fā)送請(qǐng)求時(shí),瀏覽器發(fā)現(xiàn)該請(qǐng)求不符合同源策略,會(huì)給該請(qǐng)求加一個(gè)請(qǐng)求頭:Origin,后臺(tái)進(jìn)行一系列處理,如果確定接受請(qǐng)求則在返回結(jié)果中加入一個(gè)響應(yīng)頭:Access-Control-Allow-Origin; 瀏覽器判斷該相應(yīng)頭中是否包含 Origin 的值,如果有則瀏覽器會(huì)處理響應(yīng),我們就可以拿到響應(yīng)數(shù)據(jù),如果不包含瀏覽器直接駁回,這時(shí)我們無(wú)法拿到響應(yīng)數(shù)據(jù)。所以 CORS 的表象是讓你覺(jué)得它與同源的 ajax 請(qǐng)求沒(méi)啥區(qū)別,代碼完全一樣。
CORS背后的思想,就是使用自定義的HTTP頭部讓瀏覽器與服務(wù)器進(jìn)行溝通,從而決定請(qǐng)求或響應(yīng)是應(yīng)該成功,還是應(yīng)該失敗。
1)代碼:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
if(xhr.status >= 200 && xhr.status < 304 || xhr.status == 304){
console.log(xhr.responseText);
}
}
}
xhr.open('get', 'http://www.baidu.com');
......
xhr.send(null);
降域
允許相同域名之間共享資源。
1)a.com/index.html代碼:
<div>
<input type="text" placeholder="http://a.jrg.com:8080/a.html" />
<iframe src="http://b.jrg.com:8080/b.html" frameborder="0"></iframe>
</div>
<script>
document.domain = "jrg.com"
</script>
通過(guò)document.domain = "jrg.com"降域,域名相同可以相互通信。
postMessage
postMessage()方法允許來(lái)自不同源的腳本采用異步方式進(jìn)行有限的通信,可以實(shí)現(xiàn)跨文本檔、多窗口、跨域消息傳遞。
- a.com/index.html中的代碼:
<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {
var ifr = document.getElementById('ifr');
var targetOrigin = 'http://b.com'; // 若寫(xiě)成'http://b.com/c/proxy.html'效果一樣
// 若寫(xiě)成'http://c.com'就不會(huì)執(zhí)行postMessage了
ifr.contentWindow.postMessage('I was there!', targetOrigin);
};
</script>
- b.com/index.html中的代碼:
<script type="text/javascript">
window.addEventListener('message', function(event){
// 通過(guò)origin屬性判斷消息來(lái)源地址
if (event.origin == 'http://a.com') {
alert(event.data); // 彈出"I was there!"
alert(event.source); // 對(duì)a.com、index.html中window對(duì)象的引用
// 但由于同源策略,這里event.source不可以訪問(wèn)window對(duì)象
}
}, false);
</script>
原理:
a.com/index.html 向iframe src發(fā)送消息等待處理,而不是直接修改dom元素。
b.com/index.html 監(jiān)聽(tīng)message事件,獲取到a.com的消息并做對(duì)應(yīng)處理,從而達(dá)到數(shù)據(jù)的互通。