跨域
跨域指一個(gè)域下的文檔或者腳本,去請求另一個(gè)域下面的資源。一般應(yīng)用:
- 資源跳轉(zhuǎn): A鏈接、重定向、表單提交
- 資源嵌入:
<link>、<script>、<img>、<frame>等dom標(biāo)簽,還有樣式中background:url()、@font-face()等文件外鏈- 腳本請求: js發(fā)起的ajax請求、dom和js對象的跨域操作等
同源策略
瀏覽器出于安全方面的考慮,只允許與本域下的接口交互。不同源的客戶端腳本在沒有明確授權(quán)的情況下,不能讀寫對方的資源。它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。所謂同源是指"協(xié)議+域名+端口"三者相同,即便兩個(gè)不同的域名指向同一個(gè)ip地址,也非同源。
同源策略限制的行為:
- Cookie、LocalStorage 和 IndexDB 無法讀取
- DOM 和 Js對象無法獲得
- AJAX 請求不能發(fā)送
一般跨域解決方案
1、 通過jsonp跨域
2、 document.domain + iframe跨域(此方案僅限主域相同,子域不同的跨域應(yī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一種請求。
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è)場景的跨域數(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 跨域請求資源的方式,支持現(xiàn)代瀏覽器,IE支持10以上。 實(shí)現(xiàn)方式很簡單,當(dāng)你使用 XMLHttpRequest 發(fā)送請求時(shí),瀏覽器發(fā)現(xiàn)該請求不符合同源策略,會給該請求加一個(gè)請求頭:Origin,后臺進(jìn)行一系列處理,如果確定接受請求則在返回結(jié)果中加入一個(gè)響應(yīng)頭:Access-Control-Allow-Origin; 瀏覽器判斷該相應(yīng)頭中是否包含 Origin 的值,如果有則瀏覽器會處理響應(yīng),我們就可以拿到響應(yīng)數(shù)據(jù),如果不包含瀏覽器直接駁回,這時(shí)我們無法拿到響應(yīng)數(shù)據(jù)。
普通跨域請求:只服務(wù)端設(shè)置Access-Control-Allow-Origin即可,前端無須設(shè)置,若要帶cookie請求:前后端都需要設(shè)置。