跨域
跨域指一個(gè)域下的文檔或者腳本,去請(qǐng)求另一個(gè)域下面的資源劫拗。一般應(yīng)用:
- 資源跳轉(zhuǎn): A鏈接床三、重定向、表單提交
- 資源嵌入:
<link>
杨幼、<script>
撇簿、<img>
、<frame>
等dom標(biāo)簽差购,還有樣式中background:url()四瘫、@font-face()等文件外鏈- 腳本請(qǐng)求: js發(fā)起的ajax請(qǐng)求、dom和js對(duì)象的跨域操作等
同源策略
瀏覽器出于安全方面的考慮欲逃,只允許與本域下的接口交互找蜜。不同源的客戶端腳本在沒有明確授權(quán)的情況下,不能讀寫對(duì)方的資源稳析。它是瀏覽器最核心也最基本的安全功能洗做,如果缺少了同源策略,瀏覽器很容易受到XSS彰居、CSFR等攻擊诚纸。所謂同源是指"協(xié)議+域名+端口"三者相同,即便兩個(gè)不同的域名指向同一個(gè)ip地址陈惰,也非同源畦徘。
同源策略限制的行為:
- Cookie、LocalStorage 和 IndexDB 無法讀取
- DOM 和 Js對(duì)象無法獲得
- AJAX 請(qǐng)求不能發(fā)送
一般跨域解決方案
1抬闯、 通過jsonp跨域
2井辆、 document.domain + iframe跨域(此方案僅限主域相同,子域不同的跨域應(yīng)用場(chǎng)景溶握。)
3杯缺、 location.hash + iframe (a欲與b跨域相互通信,通過中間頁c來實(shí)現(xiàn)睡榆。 三個(gè)頁面萍肆,不同域之間利用iframe的location.hash傳值袍榆,相同域之間直接js訪問來通信。)
4匾鸥、 window.name + iframe跨域(window.name屬性的獨(dú)特之處:name值在不同的頁面(甚至不同域名)加載后依舊存在蜡塌,并且可以支持非常長的 name 值(2MB)。)
5勿负、 postMessage跨域
6馏艾、 跨域資源共享(CORS)
7、 nginx代理跨域
8奴愉、 nodejs中間件代理跨域
9琅摩、 WebSocket協(xié)議跨域
jsonp跨域
在html頁面中再通過相應(yīng)的標(biāo)簽從不同域名下加載靜態(tài)資源。jsonp缺點(diǎn):只能實(shí)現(xiàn)get一種請(qǐng)求锭硼。
html+js 實(shí)現(xiàn):
<script>
function showData(ret){
console.log(ret);
}
</script>
<script src="http://api.com/weather.php?callback=showData"></script>
js 實(shí)現(xiàn):
var script = document.createElement('script');
script.type = 'text/javascript';
// 傳參并指定回調(diào)執(zhí)行函數(shù)為showData
script.src = 'http://api.com/weather.php?callback=showData';
document.head.appendChild(script);
// 回調(diào)執(zhí)行函數(shù)
function showData(res) {
console.log(JSON.stringify(res));
}
postMessage跨域
postMessage是HTML5 XMLHttpRequest Level 2中的API房资,且是為數(shù)不多可以跨域操作的window屬性之一,它可用于解決以下方面的問題:
- 頁面和其打開的新窗口的數(shù)據(jù)傳遞
- 多窗口之間消息傳遞
- 頁面與嵌套的iframe消息傳遞
- 上面三個(gè)場(chǎng)景的跨域數(shù)據(jù)傳遞
a.html (http://www.domain1.com/a.html)
<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
iframe.onload = function() {
var data = {
name: 'aym'
};
// 向domain2傳送跨域數(shù)據(jù)
iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
};
// 接受domain2返回?cái)?shù)據(jù)
window.addEventListener('message', function(e) {
alert('data from domain2 ---> ' + e.data);
}, false);
</script>
b.html(http://www.domain2.com/b.html)
<script>
// 接收domain1的數(shù)據(jù)
window.addEventListener('message', function(e) {
alert('data from domain1 ---> ' + e.data);
var data = JSON.parse(e.data);
if (data) {
data.number = 16;
// 處理后再發(fā)回domain1
window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com');
}
}, false);
</script>
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í)我們無法拿到響應(yīng)數(shù)據(jù)股缸。
普通跨域請(qǐng)求:只服務(wù)端設(shè)置Access-Control-Allow-Origin即可,前端無須設(shè)置容为,若要帶cookie請(qǐng)求:前后端都需要設(shè)置乓序。