摘要:常用跨域方法總結(jié)為什么要跨域因為瀏覽器的一種安全機制同源策略的限制,導(dǎo)致不能直接獲取不同源的資源,所以要跨域。那么什么才叫同源呢協(xié)議相同域名相同端口號相同圖來自參見最后下面介紹常用的幾種跨域方法。
常用跨域方法總結(jié) 為什么要跨域?
因為瀏覽器的一種安全機制——同源策略的限制,導(dǎo)致不能直接獲取不同源的資源,所以要跨域。
同源策略限制了從同一個源加載的文檔或腳本如何與來自另一個源的資源進(jìn)行交互。這是一個用于隔離潛在惡意文件的重要安全機制。
限制之一是不能通過ajax的方法去請求不同源中的文檔。
第二個限制是瀏覽器中不同域的框架(iframe)之間是不能進(jìn)行js的交互操作的。
那么什么才叫“同源”呢?
協(xié)議相同
域名相同
端口號相同
圖來自MDN,參見最后Reference.
下面介紹常用的幾種跨域方法。
jsonp 跨域原理:
利用了標(biāo)簽不受瀏覽器同源限制的影響,
因為借用發(fā)起的請求,所以會把請求到的內(nèi)容當(dāng)作js代碼來解析執(zhí)行。
缺點:只能發(fā)送get請求
下面是一個簡單的例子
Title
如上,定義了一個全局的callback 函數(shù),然后利用來發(fā)起get請求,注意把函數(shù)名稱callback 一同發(fā)送給服務(wù)端,為什么呢,接著往下看服務(wù)端代碼
//nodeJs var http = require("http"); var url = require("url"); /** * 客戶端請求的函數(shù) * @param req * @param res */ function onRequest (req, res) { console.log("獲取到的請求參數(shù)的路徑:" + req.url); //得到鍵值對 var arg = url.parse(req.url, true).query; //打印鍵值對中的值 console.log(arg.cb); res.writeHead(200); res.write(arg.cb + "("我今天要用jsonp來跨域獲取數(shù)據(jù)")"); res.end(); } http.createServer(onRequest).listen(8080);
服務(wù)端簡單解析cb參數(shù)(我們傳的函數(shù)名稱),然后返回一段字符串callback("我今天要用jsonp來跨域獲取數(shù)據(jù)")
瀏覽器會收到響應(yīng)如下:
發(fā)現(xiàn)什么了嗎?響應(yīng)內(nèi)容callback("我今天要用jsonp來跨域獲取數(shù)據(jù)")會被當(dāng)作js代碼來執(zhí)行,正好調(diào)用了我們之前定義的callback函數(shù)。
由此,我們成功的利用jsonp通過跨域獲取到了想要的數(shù)據(jù)。
開頭我們說到不同源的框架之間是不能進(jìn)行js交互操作的,其實是可以獲取window對象,但不能獲取window的屬性。
原理:
document.domain的值是可以設(shè)置的,但僅限于設(shè)置為自身或是更高一級的父級域名(主域名相同)。
那么主域名相同,子域名不同的框架之間跨域獲取數(shù)據(jù)的思路就來了,我們把它們的document.domain都設(shè)置成主域名不就完事了?
比如有一個頁面a.google.com/1.html
這里參考了其他文章的代碼。出處見本文最下方
另一個頁面b.google.com/2.html只需設(shè)置主域名為google.com,兩個框架間就可以進(jìn)行交互啦。
location.hash跨域(不同源的框架之間)原理:
hash字段(經(jīng)常用于錨點定位)不屬于http協(xié)議的部分,請求不會攜帶hash信息,所以改變不會重新請求資源(但是會產(chǎn)生新的瀏覽器歷史記錄,許多前端路由也是借用這個原理實現(xiàn)的)
父窗口可以對iframe進(jìn)行URL讀寫,iframe也可以讀寫父窗口的URL(不同源的話,IE、Chrome不允許修改parent.location.hash的值,但我們?nèi)杂刑幚矸绞剑?/p>
思路:
如果是父窗口向子窗口跨域傳遞數(shù)據(jù),直接修改子窗口url的hash就可以了,比較簡單這里就不貼代碼了。
子窗口向父親窗口跨域傳遞數(shù)據(jù)就需要多加一個代理窗口(因為IE,Chrome),這個代理窗口和父親窗口同源就可以了,在這個代理窗口改變父親窗口的hash,父親窗口監(jiān)聽hashchange就可以了。
代碼如下:
父親窗口頁面
http://localhost:63342/test-field/cross-origin/local-test/hash-parent.html
Title
子窗口頁面
http://blank121.github.io/tes...
try{ parent.location.hash="今天我要用hash跨域" //chrome ie 直接修改parent.location.hash報錯 }catch (e){ var iframe = document.createElement("iframe") iframe.src = "https://localhost:63342/test-field/cross-origin/local-test/hash-proxy.html"+"#今天我要用hash跨域" document.body.appendChild(iframe); }
代理窗口頁面
http://localhost:63342/test-field/cross-origin/local-test/hash-proxy.html
Title
如上,在子窗口頁面內(nèi)修改了代理窗口的hash值,代理窗口又修改了父親窗口的hash值,父親窗口監(jiān)聽hashchange就可以獲取到不同源的子窗口傳來的數(shù)據(jù)啦。
控制臺結(jié)果如下:
原理:
window對象有個name屬性,該屬性有個特征:即在一個窗口(window)的生命周期內(nèi),窗口載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的權(quán)限,window.name是持久存在一個窗口載入過的所有頁面中的,并不會因新頁面的載入而進(jìn)行重置。
利用一個窗口的生命周期內(nèi),載入不同頁面window.name不變的特性
貼代碼前首先去做個有趣的實驗
在必應(yīng)的首頁設(shè)置一下window.name
然后輸入location.href = "http://www.baidu.com",跳轉(zhuǎn)到百度后再看一下name
666,window.name果然沒騙我,沒有變化。
接下來先貼代碼
父親窗口:
http://localhost:63342/test-field/cross-origin/local-test/name-parent.html
Title
子窗口:
https://blank121.github.io/te...
window.name跨域
代理窗口(啥也沒做。主要是要和父親窗口同源來傳遞name)
Title
代碼如上,主要思路就是利用window.name不變性,子窗口設(shè)置了name之后,來加載一個和父親窗口同源的代理窗口,以此來獲取name(注意子窗口和代理窗口是同一個iframe,加載不同頁面而已,所以window.name不變)
postMessage跨域首先了解一下postMessage
otherWindow.postMessage(message, targetOrigin);
otherWindow:指目標(biāo)窗口,也就是給哪個window發(fā)消息,是 window.frames 屬性的成員或者由 window.open 方法創(chuàng)建的窗口
message: 是要發(fā)送的消息,類型為 String、Object (IE8、9 不支持)
targetOrigin: 是限定消息接收范圍,不限制請使用 *
postMessage是HTML5新特性,跨域簡直太方便了,就是兼容性要注意一下。
發(fā)送方頁面
Title
接收方頁面
Title
接收方監(jiān)聽一下message事件,就可以接收到信息啦。
WebSocket跨域WebSocket 是一種在客戶端與服務(wù)器之間保持TCP長連接的網(wǎng)絡(luò)協(xié)議,這樣它們就可以隨時進(jìn)行信息交換(雙工通訊)。
雖然任何客戶端或服務(wù)器上的應(yīng)用都可以使用WebSocket,但原則上還是指瀏覽器與服務(wù)器之間使用。通過WebSocket,服務(wù)器可以直接向客戶端發(fā)送數(shù)據(jù),而無須客戶端周期性的請求服務(wù)器,以動態(tài)更新數(shù)據(jù)內(nèi)容。
WebSocket 非常強大,筆者在這方面也是小白級別的,以后有時間會詳細(xì)研究學(xué)習(xí)。
跨域代碼如下
頁面:
Title
服務(wù)端nodeJs代碼:
var WebSocketServer = require("ws").Server; var wss = new WebSocketServer({ port: 8080 }); wss.on("connection", function connection(ws) { ws.on("message", function incoming(message) { console.log("received: %s", message); ws.send("hello"+message); }); });
結(jié)果如圖:
瀏覽器端:
服務(wù)端:
完美實現(xiàn)了跨域。
CORS(cross origin resource sharing 最常用)老生常談的CORS,優(yōu)秀的文章已經(jīng)非常多了,大家可以搜一下,非常重要,有機會我會專門寫一篇文章來學(xué)習(xí)總結(jié),在此就不再詳述了
最后不得不說,這些方法還是比較巧妙的,在此寫下一篇文章來總結(jié)一下,感覺自己面對跨域絲毫不慌啦。
Reference前端跨域整理
正確面對跨域,別慌
瀏覽器的同源策略
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/95698.html
摘要:常用跨域方法總結(jié)為什么要跨域因為瀏覽器的一種安全機制同源策略的限制,導(dǎo)致不能直接獲取不同源的資源,所以要跨域。那么什么才叫同源呢協(xié)議相同域名相同端口號相同圖來自參見最后下面介紹常用的幾種跨域方法。 常用跨域方法總結(jié) 為什么要跨域? 因為瀏覽器的一種安全機制——同源策略的限制,導(dǎo)致不能直接獲取不同源的資源,所以要跨域。 同源策略限制了從同一個源加載的文檔或腳本如何與來自另一個源的資源進(jìn)行...
摘要:常用跨域方法總結(jié)上篇文章介紹了幾種常用的跨域方法常用跨域方法總結(jié),本片為上一篇的補充,對比較重要的詳細(xì)介紹。出于安全原因,從腳本內(nèi)發(fā)起的跨源請求會受到一定限制。當(dāng)開發(fā)者使用對象發(fā)起跨域請求時,它們已經(jīng)被設(shè)置就緒。 常用跨域方法總結(jié)(2)——CORS 上篇文章介紹了幾種常用的跨域方法:常用跨域方法總結(jié),本片為上一篇的補充,對比較重要的Cross Origin Resource Shari...
摘要:常用跨域方法總結(jié)上篇文章介紹了幾種常用的跨域方法常用跨域方法總結(jié),本片為上一篇的補充,對比較重要的詳細(xì)介紹。出于安全原因,從腳本內(nèi)發(fā)起的跨源請求會受到一定限制。當(dāng)開發(fā)者使用對象發(fā)起跨域請求時,它們已經(jīng)被設(shè)置就緒。 常用跨域方法總結(jié)(2)——CORS 上篇文章介紹了幾種常用的跨域方法:常用跨域方法總結(jié),本片為上一篇的補充,對比較重要的Cross Origin Resource Shari...
閱讀 2597·2021-09-29 09:34
閱讀 3414·2021-09-23 11:21
閱讀 2590·2021-09-06 15:00
閱讀 1180·2019-08-30 15:44
閱讀 2091·2019-08-29 17:23
閱讀 3082·2019-08-29 16:44
閱讀 3119·2019-08-29 13:13
閱讀 2034·2019-08-28 18:12