跨域是什么
- 跨域,指的是當(dāng)一個(gè)資源向另一個(gè)與該資源本身所在服務(wù)器不同域或端口的服務(wù)器請(qǐng)求一個(gè)資源時(shí)席爽,資源會(huì)發(fā)起一個(gè)跨域HTTP 請(qǐng)求。例如:站點(diǎn) http://a.com中的某個(gè)圖片的
src
地址為 http://b.com 時(shí),就是發(fā)起了一次跨域http請(qǐng)求卵惦。 - 出于安全考慮,瀏覽器會(huì)對(duì)ajax的跨域請(qǐng)求進(jìn)行限制瓦戚,其具體表現(xiàn)為瀏覽器會(huì)攔截跨域請(qǐng)求返回的內(nèi)容沮尿。而其他的標(biāo)簽如
script
、link
较解、img
等發(fā)送的跨域請(qǐng)求則會(huì)正常返回內(nèi)容畜疾。
同源策略是什么
- 同源策略,指的是一種限制一個(gè)源的資源與來(lái)自另一個(gè)源的資源進(jìn)行交互的策略哨坪,這是一個(gè)用于隔離潛在惡意文件的關(guān)鍵的安全機(jī)制庸疾。
- 這個(gè)策略具體指的是要在同協(xié)議、同域名当编、同端口的前提下届慈,才能夠進(jìn)行資源請(qǐng)求
- 遵守這個(gè)策略的有
XMLHttpRequest
和Fetch
有哪些跨域的解決方法
- JSONP徒溪。JSONP的原理是利用
script
標(biāo)簽不受同源策略的限制,這種做法需要前端和后端的配合金顿。例子如下:
// btn為某個(gè)按鈕
btn.addEventListener('click', function () {
var script = document.creatElement('div');
script.src = 'www.xxx.com?callback=' + handle;
document.head.appendChild(script);
document.head.removeChild(script);
});
// handle為自定義的函數(shù)
function handle(data){}
在上面的例子中臊泌,先創(chuàng)造一個(gè) script
標(biāo)簽,然后把 src
賦值為后端的地址再加上 ?callback=handle
揍拆,其中 handle
為自定義的函數(shù)的名字渠概,再利用 script
標(biāo)簽向目標(biāo)發(fā)送跨域請(qǐng)求。目標(biāo)接收到請(qǐng)求后嫂拴,解析里面的 callback
參數(shù)播揪,然后返回函數(shù)包含數(shù)據(jù)的格式,例如 res.send(callback+'('+JSON.stringify(data)+')') // data為要返回的數(shù)據(jù)
筒狠。等到腳本加載完畢后猪狈,handle
函數(shù)就會(huì)自動(dòng)執(zhí)行,從而能夠處理跨域請(qǐng)求的數(shù)據(jù)
- CORS辩恼」兔恚跨域資源共享(CORS)機(jī)制允許 Web 應(yīng)用服務(wù)器進(jìn)行跨域訪問(wèn)控制,從而使跨域數(shù)據(jù)傳輸?shù)靡园踩M(jìn)行灶伊。使用該機(jī)制的是
XMLHttpRequest
和Fetch
疆前,突破了ajax同源策略的限制。使用這個(gè)機(jī)制也需要后端的配合聘萨。例子如下:
btn.addEventListener('click', function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = handle;
xhr.open('get', 'www.xxxx.com?aaa=1', true);
xhr.send();
});
上面的例子與普通ajax的請(qǐng)求代碼沒(méi)什么不同竹椒,然而這樣通過(guò)ajax發(fā)起跨域請(qǐng)求所返回的數(shù)據(jù)則會(huì)被瀏覽器攔截。這個(gè)時(shí)候需要讓后端返回?cái)?shù)據(jù)之前要設(shè)置一個(gè)返回頭匈挖,如 res.setHeader('Access-Control-Allow-Origin', '*') // 第二個(gè)參數(shù)為允許訪問(wèn)的域名碾牌,*表示允許所有域名
。當(dāng)瀏覽器讀取到數(shù)據(jù)的返回頭時(shí)儡循,如果返回頭的 Access-Control-Allow-Origin
字段后面的域名和發(fā)起請(qǐng)求的域名一樣舶吗,那么瀏覽器就不會(huì)攔截返回的數(shù)據(jù)。通過(guò)這種后端限制域名的方式择膝,可以使跨域數(shù)據(jù)傳輸更安全
降域誓琼。對(duì)于主域相同而子域不相同的情況,可以使用降域的操作肴捉。例如有
http://a.ccc.com
和http://b.ccc.com
兩個(gè)網(wǎng)站腹侣,而且在http://a.ccc.com
上通過(guò)iframe
引入http://b.ccc.com
,這時(shí)候如果想在a網(wǎng)站的腳本上操控b網(wǎng)站上的元素(跨域操作)齿穗,那么可以給兩個(gè)網(wǎng)站的腳本都設(shè)置document.domain = 'ccc.com' // domain的值為主域名
傲隶,這樣a網(wǎng)站就可以跨域操控b網(wǎng)站上的元素了postMessage。HTML5增加了postMessage方法窃页,用于跨域傳輸信息跺株。例如
http://www.a.com
向iframe
里的http://www.b.com
發(fā)送消息:
// http://www.a.com
<iframe src="http://www.b.com" frameborder="0"></iframe>
<script>
window.iframes[0].onload = function () {
window.iframes[0].postMessage('hello', '*'); // 第二個(gè)參數(shù)為目標(biāo)的URI地址复濒,如果窗口地址與第二個(gè)參數(shù)的URI不匹配,則不會(huì)發(fā)送消息
}
</script>
// http://www.b.com
window.addEventListener('message', function (e) {
console.log(e.data);
});