跨域問題
前言
近期回顧自己之前弄的思維導(dǎo)圖晦攒,這部分還可以再稍微細(xì)點(diǎn),寫點(diǎn)東西記錄下
原因
跨域問題問題產(chǎn)生的原因是由于同源策略得哆。
同源是指"協(xié)議+域名+端口"三者相同脯颜。
同源策略是瀏覽器的行為,是為了保護(hù)本地?cái)?shù)據(jù)不被JavaScript代碼獲取回來的數(shù)據(jù)污染贩据,因此攔截的是客戶端發(fā)出的請求回來的數(shù)據(jù)接收栋操,即請求發(fā)送了,服務(wù)器響應(yīng)了饱亮,但是無法被瀏覽器接收矾芙。
JSONP
因?yàn)閕mg,css,script等標(biāo)簽 不受同源策略影響,可以基于此策略近上,
利用script標(biāo)簽可以跨域的特點(diǎn)來發(fā)起跨域請求剔宪,后端返回一個(gè)函數(shù),前端調(diào)用此函數(shù)壹无,即完成的此次的請求
示例:
function jsonp() {
var script = document.createElement('script');
script.type = 'text/javascript';
// 傳參并指定回調(diào)執(zhí)行函數(shù)為backFn
script.src = 'http://localhost:8100/getUserInfo?uid=100&callback=backFn';
document.head.appendChild(script);
}
// 回調(diào)執(zhí)行函數(shù)
function backFn(res) {
alert(JSON.stringify(res));
}
document.getElementById('btn_get_data').addEventListener('click',()=>{
jsonp();
});
JSONP方案可以兼容各種瀏覽器葱绒,但只支持get請求
CORS
2014年1月16號CORS作為http協(xié)議的擴(kuò)充部分正式發(fā)布,主要定義了客戶端和服務(wù)端的溝通機(jī)制斗锭,也就是所謂的協(xié)議地淀。
CORS需要瀏覽器和服務(wù)器同時(shí)支持。目前所有瀏覽器都支持該功能岖是,IE瀏覽器不能低于IE10帮毁。
瀏覽器將CORS請求分成兩類:
- 簡單請求(simple request)
- 非簡單請求(預(yù)檢請求)(not-so-simple request)她倘。
同時(shí)滿足以下兩大條件,就屬于簡單請求作箍,否則就是非簡單請求
(1) 請求方法是以下三種方法之一:
HEAD
GET
POST
(2)HTTP請求頭信息不超出以下幾種字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三個(gè)值application/x-www-form-urlencoded硬梁、multipart/form-data、text/plain
簡單請求
對于簡單請求胞得,瀏覽器直接發(fā)出CORS請求荧止。具體來說,就是在頭信息之中阶剑,增加一個(gè)Origin字段跃巡。
非簡單請求
非簡單請求的CORS請求,會在正式通信之前牧愁,增加一次HTTP查詢請求素邪,稱為"預(yù)檢"請求(preflight)。
瀏覽器先詢問服務(wù)器猪半,當(dāng)前網(wǎng)頁所在的域名是否在服務(wù)器的許可名單之中兔朦,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答復(fù)磨确,瀏覽器才會發(fā)出正式的XMLHttpRequest請求沽甥,否則就報(bào)錯。
PostMessage
postMessage是html5引入的API可以更方便乏奥、有效摆舟、安全的解決這些問題。postMessage()方法允許來自不同源的腳本采用異步方式進(jìn)行有限的通信邓了,可以實(shí)現(xiàn)跨文本檔恨诱、多窗口、跨域消息傳遞骗炉。
- 頁面和其打開的新窗口的數(shù)據(jù)傳遞
- 多窗口之間消息傳遞
- 頁面與嵌套的iframe消息傳遞
- 上面三個(gè)場景的跨域數(shù)據(jù)傳遞
postMessage(data,origin)方法接受兩個(gè)參數(shù)
data: html5規(guī)范支持任意基本類型或可復(fù)制的對象照宝,但部分瀏覽器只支持字符串,所以傳參時(shí)最好用JSON.stringify()序列化痕鳍。
origin: 協(xié)議+主機(jī)+端口號硫豆,也可以設(shè)置為"*",表示可以傳遞給任意窗口笼呆,如果要指定和當(dāng)前窗口同源的話設(shè)置為"/"熊响。
Websocket
WebSocket 是 HTML5 開始提供的一種在單個(gè) TCP 連接上進(jìn)行全雙工通訊的協(xié)議。
var Socket = new WebSocket(url, [protocol] );
第一個(gè)參數(shù) url, 指定連接的 URL诗赌。第二個(gè)參數(shù) protocol 是可選的汗茄,指定了可接受的子協(xié)議。
基本用法
// 初始化一個(gè) WebSocket 對象
var ws = new WebSocket("ws://localhost:9998/echo");
// 建立 web socket 連接成功觸發(fā)事件
ws.onopen = function () {
// 使用 send() 方法發(fā)送數(shù)據(jù)
ws.send("發(fā)送數(shù)據(jù)");
alert("數(shù)據(jù)發(fā)送中...");
};
// 接收服務(wù)端數(shù)據(jù)時(shí)觸發(fā)事件
ws.onmessage = function (evt) {
var received_msg = evt.data;
alert("數(shù)據(jù)已接收...");
};
// 斷開 web socket 連接成功觸發(fā)事件
ws.onclose = function () {
alert("連接已關(guān)閉...");
};
Cookie與iframe
如果兩個(gè)網(wǎng)頁一級域名相同铭若,二級域名不同洪碳,游覽器允許通過document.domain共享Cookie與iframe.
cookie的存儲大小偏小
iframe 缺點(diǎn):
1.會阻塞主頁面的onload事件
2.和主頁面共享連接池递览,而瀏覽器對相同域名的連接有限制,會影響頁面并行加載
3.不利于SEO
由于1和2問題瞳腌,最好通過js動態(tài)給iframe添加src屬性來避免1绞铃、2問題