摘要:什么是跨域我們先看下以下場景開啟兩個本地服務器,頁面為,其中嵌套了,頁面想使用頁面的數據,例如調用它的方法,會報以下錯誤如圖所示,,,譯為協議主機和端口號必須符合,否則,就是跨域??缬虻膸追N常見方案同源策略的限制范圍有以下幾種和無法讀取。
什么是跨域
我們先看下以下場景:
開啟兩個本地服務器,頁面A為localhost:9800,其中嵌套了iframeB localhost:9000,頁面A想使用頁面B的數據,例如調用它的方法,會報以下錯誤
如圖所示,Protocols,domains,and ports must match. 譯為:協議、主機和端口號必須符合,否則,就是跨域。
下面我們來具體談談。
瀏覽器的同源策略我們都知道,瀏覽器有個同源策略,也就是這個策略,限制了兩個源中的資源相互交互。
Two pages have the same origin if the protocol, port (if one is specified), and host are the same for both pages.譯為:如果兩個頁面有相同的協議、端口號和主機,那么這兩個頁面就屬于同一個源。
也就是說,只有同一個源才可以進行資源共享。
我們來舉幾個例子,如果想和 http://www.test.com/index.html 進行通信:
URL | Result | Reason |
---|---|---|
http://www.test.com/page/othe... | 允許 | |
http://www.test.com/index.js | 允許 | |
http://a.test.com/index.html | 不允許 | 子域不同 |
http://www.other.com/index.html | 不允許 | 主域不同 |
https://www.test.com/index.html | 不允許 | 協議不同 |
http://www.test.com:3000/index.html | 不允許 | 端口不同 |
我們可以看到,協議、端口、主機缺一不可,必須完全匹配,上文就是由于端口號不同而報錯。
那為什么要有同源策略的限制呢?原因也很簡單,就是為了保證用戶信息的安全,防止惡意的網站竊取數據。
試想一下,如果我們可以隨意訪問一個網站的cookie,那么豈不是隨意竊取別別人登陸的cookie?如果沒有同源策略,那互聯網就太危險了。
跨域的幾種常見方案同源策略的限制范圍有以下幾種:
Cookie、LocalStorage 和 IndexDB 無法讀取。
DOM 無法獲得。
AJAX 請求不能發送。
而跨域訪問,也無非兩種情況:一是請求不同源下的接口(如上第3種);二是請求不同源的頁面的資源(如上1、2,通常是頁面中嵌套不同源的iframe要進行通信)。本文主要討論第二種情況下造成的跨域,方法很多,主要介紹以下幾種:document.domain、location.hash、window.name、postMessage。
document.domain適用于:主域相同子域不同的頁面,例如上例中的第三種
方法:只需將這兩個頁面的document.domain設置為相同的父域名,即可實現不同子域名之間的跨域通信。
location.hash
一般來說,URL的任何改變都重新會加載一個新的網頁,除了hash的變化,hash的任何改變都不會導致頁面刷新。
在跨域解決方案中,hash也非常有用,來自不同源的頁面可以相互設置對方的 URL,包括hash值,但不能獲取對方的hash值。文檔之間可以通過hash來相互通信。
流程(如上圖):
主頁面A中嵌入iframeB,兩個來自不同域
在主頁面A中,將想要傳遞給B的字段,作為hash,將它與B的url連接起來,然后將B的src設置為連接后的url
在iframeB中,就可以通過獲取自己url的hash值,從而得到主頁面傳遞的值,但在iframeB中,需設置一個定時器監聽hash值的變化
除了設置定時器,還可以通過監聽window.onhashchange事件
例子:啟動兩個本地服務器,主頁面localhost:9800,子頁面localhost:9000,主頁面向子頁面發消息
結果如下:點擊button后,子頁面將收到主頁面的消息
注意:使用hash時最好對其進行編碼、解碼,否則在Firefox中會報錯。因為Firefox會自動將hash值進行編碼,如果不進行解碼就無法JSON.parse().
兩個頁面不同源的情況下,IE、Chrome不允許修改parent.location.hash的值(Firefox可以),所以如果主頁面想從子頁面獲取消息,只能借助一個代理iframe設置。
流程如下(兩種):
子頁面創建隱藏的代理iframe,與主頁面同源,并將消息作為hash,設置到iframe的src中
代理頁面將主頁面的hash值設置為自身的hash
主頁面使用定時器監聽hash的變化
例子如下
結果如圖:
這種方法的劣處就是將消息暴露在url中,因此也可以采用下文將講述利用代理iframe跨域的方法,這邊就不贅述了。
由于現在許多網站的hash已經被用于其他用途,此時想用hash跨域就會比較復雜了。這種情況下,我們可以使用一個同域的代理頁面來完成
頁面A想向頁面B發送數據,流程如下:
頁面A創建一個隱藏的代理iframeC,這個iframe與頁面B同域
頁面A中,將要發送的數據,作為hash,與頁面C的url連接起來
在代理iframeC中,它與B同域,可以直接調用頁面B中的方法,這樣便可以將hash值傳遞給B了
例子如下
結果如下:
缺點:
數據直接暴露在url中,安全性較低
url大小是有限制的,它支持傳遞的數據量較小
window.name加載任何頁面 window.name 的值始終保持不變
當頁面A想從頁面B中獲取數據時:
頁面A,創建一個隱藏的iframeC,將C的src指向頁面B
頁面C加載完成后,把響應的數據附加到window.name上
C 取到數據后,將src設為任何一個與A同源的頁面,這時 A 就能獲取到 B 的name屬性值
A 取到數據后,隨時可以刪掉 C
例子,啟動兩個本地服務器,頁面Alocalhost:9800,頁面Blocalhost:9000,頁面A想從頁面B中獲取數據
結果如圖
另外,兩個頁面還可相互通信
頁面A通過hash,將數據傳遞給頁面B,頁面B仍通過window.name向頁面A傳遞數據
場景如下:頁面B存儲了一些人的信息,頁面B通過頁面A的輸入,獲取不同人的信息
輸入想獲得的數據的id值,即可得到相應的信息
總結:
優點:容量很大,可以放置很長的字符串(2M左右,比url大得多)
缺點:必須要監聽window.name屬性的變化
HTML5規范中的新方法window.postMessage()可以用于安全跨域通信。當該方法調用時,將分發一個消息事件。對應的窗口通過事件監聽來獲取消息。
語法 :otherWindow.postMessage(message, targetOrigin)
otherWindow代表其他窗口的引用,例如iframe的contentWindow屬性,通過window.open返回的窗體,通過window.frames[]返回的ifame對象。
message表示發送給其他窗口的數據
targetOrigin指定哪些來源的窗口可以接收到消息事件,其值可以是字符串"*"(表示無限制)或"/"(表示與父窗口同源)或一個URI。發送消息時,只有目標窗口的協議、主機、端口這三項都匹配targetOrigin提供的值,消息才會發送。
接收消息的窗口可以通過監聽message事件,去接收消息
window.addEventListener("message", receiveMessage, false);
receiveMessage為接收到消息后的操作
message事件的事件對象event,提供三個屬性:
event.source:發送消息的窗體(可以用來引用父窗口)
event.origin:消息發向的網址(可以過濾不是發給本窗口的消息)
event.data:消息內容
例子:啟動兩個本地服務器,頁面Alocalhost:9800,頁面Blocalhost:9000,頁面A根據頁面B發來的數據改變顏色
結果如下:點擊按鈕后,頁面的div由灰變藍
結語關于跨域的就先聊到這啦~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88072.html
摘要:如果像本例中這樣的場景會遇到這樣一個問題,詳見鏈接當請求參數過長或為了安全,就需要用到下載。寫到這里自己都忍不住想錘自己,給自己挖坑不說,這樣來回請求下載,流量,真的是敗家。 這幾天一直在做遠程文件下載的事,現在總算有了解決,特來記錄一下踩過的坑和想揍自己的心 需求 應用場景是這樣的,底層邏輯數據請求接口是由Java寫的,也就是說原始文件存在Java服務端,返回時有加密措施 由于工作...
摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼什么是功能統計作為一名開發,我們的產品發布出去之后,無論是產品還是運營,其實都是想及時了解產品對用戶產生的影響的。下一章,我們將繼續聊聊速度統計。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/bl...
閱讀 3564·2023-04-26 00:05
閱讀 954·2021-11-11 16:55
閱讀 3522·2021-09-26 09:46
閱讀 3517·2019-08-30 15:56
閱讀 909·2019-08-30 15:55
閱讀 2934·2019-08-30 15:53
閱讀 1940·2019-08-29 17:11
閱讀 814·2019-08-29 16:52