摘要:在所有以上提到的跨域方法中,不得不說都是利用了大大小小的漏洞來繞過同源策略。對于開發者來說最大的好處就是,無需考慮以什么樣的方式繞過同源策略請求跨域資源,直接使用即可。
HTML跨域 傳統跨域方式 JSONP跨域
說到傳統跨域方式,JSONP是最廣泛為人所知的形式了。
對于JS來說,利用XMLHttpRequest無法請求非本域上的數據,但是卻可以加載非本域的JS文件。
JSONP就是利用了這個所謂的“漏洞”。
試想當我們在文檔中插入一個script標簽,請求一個 JS 文件時,該JS文件的內容是直接調用一個函數,
同時傳入適當的數據。則對于方法內部,就已經可以通過參數的形式獲取傳入的數據。如下所示:
此處的對象,就是傳入的數據,而fun則是那個函數。該函數其實可以是任意函數名,只需在我們的window域下定義,也可以根據需求定義在其他地方。問題在于傳入的數據怎么來呢?其實這些對于前端來說完全不用管,只需讓后端處理好后拼接成如上形式返回給我們即可。而fun里面放什么,則取決于你要對返回的數據做什么樣的處理了。
另外,fun的函數名建議是隨同跨域接口一起傳輸給server,以讓server來進行拼接出合適的執行代碼。完整代碼如下:
document.domain也許你會遇到這樣的情形:我的網頁內嵌了一個iframe,該iframe所引用的頁面跟我本域不一樣,此時我想修改iframe中的內容,該怎么辦呢?
或許你認為可以通過contentWindow獲取iframe中的內容,但很可惜的是我們拿到這個contentWindow,卻不能獲取到里面的屬性與方法(H5最新屬性postMessage除外,后面會提及)。
這是因為瀏覽器的同源策略禁止了我們這樣的操作,因為它們分屬不同的源。
此時就需要用到document.domain了,也就是我們只需將iframe中的document.domain設置成跟父頁面相同的值即可。
比如當 http://loliner.baidu.com/inde... 內嵌了 http://baidu.com/example.html ,此時我們只需將 index.html 的 document.domain 修改成 baidu.com即可實現與example.html通信。
但是問題來了,瀏覽器對document.domain的設置是有限制的,其只能設置成比自身域更高一級的域名,包括自身域。
比如存在http://b.a.com/index.html,則該頁面 document.domain允許的值為
b.a.com a.com
而c.b.a.com則是不允許的。且兩個頁面若要通訊,則兩者的主域必須相同。
上例中,主域就為 baidu.com。
window.name在一個窗口(window)的生命周期內,窗口載入的所有的頁面都是共享一個window.name,每個頁面對window.name都有讀寫的權限。
以上是對window.name的定義。試想如果有兩個不同域的頁面順次被同一個窗口加載,那么對于這兩個頁面來說,兩者就能共享window.name,從而實現通信。
如何順次加載?利用window.location改變窗口的地址就可以辦到這一點。
比如,http://example.com/a.html 完全加載后,修改window.name為指定值。然后通過window.location將窗口定向到 http://loliner.com/b.html,此時b.html中window.name的值就為上一個頁面中設置的值。
window.name的值只能是一個字符串,最大2M,但對我們來說已經夠用了。如果你要傳遞對象或數組,進行JSON格式化即可。
但是,雖然這樣實現了數據通信,但是我們不能來回這樣切來切去,那怎么辦呢?這時候就可以利用 iframe + contentWindow 了。
我們可以在 b.html 頁面添加一個隱藏的iframe,該iframe指向a.html,當a.html完全加載并修改了window.name之后,我們將iframe重新指向與b.html在同一個域名下的c.html,此時就可以通過 iframe 的 contentWindow 獲取到 name 的值了。
完整代碼如下:
H5跨域方式 window.postMessage我們知道在同一個頁面嵌入多個iframe,每個iframe的域都不一樣時,雖然我們可以獲取iframe的window對象,卻不能訪問其中的屬性和方法。但H5的最新屬性postMessage除外,那么我們是否可以在此利用這樣的一個“漏洞”來進行跨域呢?
答案是可以的。
我們只需在iframe中設置onmessage監聽,然后在父級頁面中獲取iframe的window對象,將父頁面所要傳遞的信息通過window.postMessage發出即可。
完整代碼如下:
首先要讓iframe監聽onmessage事件。
接下來則是在父頁面中獲取iframe的window對象并調用postMessage傳遞信息。
注意,此處的postMessage所發送的消息在低版本瀏覽器下只能為字符串,若要傳遞對象或數組,只能JSON格式化。
另外,第二個參數指的是域,表示你要將信息發送到哪個域,參數格式為協議+主機+端口,其實跟上面所說document.domain的值是一回事。
CORS在所有以上提到的跨域方法中,不得不說都是利用了大大小小的漏洞來繞過同源策略。而無論如何進行繞過,有一點可以肯定的是,WEB開發當中確實需要跨域獲取資源。
所以,W3C為我們制訂了 CORS 跨域訪問機制。CORS對于開發者來說最大的好處就是,無需考慮以什么樣的方式繞過同源策略請求跨域資源,直接使用ajax即可。
那么誰去負責跨域的安全性呢?答案是由Server進行控制。
Server在接收到請求的時候,需判斷請求來源,如果該來源合法,返回正常數據,同時需要在請求返回頭response header中添加必要 CORS 字段。
對于瀏覽器來說,若該請求的返回頭信息中,包含該 CORS 字段,那么瀏覽器就會正常讀取返回的信息,否則,就會拋出No "Access-Control-Allow-Origin" header is present on the requested resource.禁止跨域異常。
上面所說到的CORS字段,分為必須與可選:
Access-Control-Allow-Origin(必須)
該服務器所允許跨域的源,如果為 * ,則表示允許所有源對該服務器進行請求。
發送請求的一方的域,必須包含在該值所指定的源內。
Access-Control-Allow-Credentials(可選)
表示是否允許發送cookie,該值為一個布爾值,默認為false。
Access-Control-Expose-Headers(可選)
獲取response header中其他字段的值。
所以,簡單的說,CORS 模式中的跨域請求其實與前端開發者已經沒有太大的關系,只要Server端控制好接口數據,并按需寫入CORS字段即可。
另外,CORS跨域請求可以分為簡單請求與復雜請求。
簡單請求對于簡單請求,瀏覽器直接發送CORS請求即可,跟上面所說流程一致。
HEAD、GET、POST都屬于簡單請求。復雜請求
對于復雜請求,則需要首先發出預檢請求,判斷是否可以跨域,然后再發送真實請求。
PUT和DELETE,或Content-Type字段類型為application/json的都屬于復雜請求。
就目前來說,JSONP 及 CORS 算是最常用的跨域形式了,也能滿足我們的絕大部分需求。
相對于JSONP,CORS W3C規定的標準跨域方式,功能更強大,安全性也更好。
JSONP只支持GET請求,而 CORS 支持多種請求。
JSONP 沒有域的概念,CORS 則有精確的指定哪些域可以獲取資源。
CORS 將域的安全性管理完全交給Server管理,更加安全。
Flash跨域Flash跨域也有多種形式,此處只介紹最常用的 crossdomain.xml 策略文件 模式及allowDomain 權限授予。
corssdomain.xml 跨域策略文件
與 CORS 復雜請求一樣,Flash在進行跨域請求時,默認首先會發送預檢請求,判斷本域是否合法。該預檢請求會去跨域請求的根目錄獲取 corssdomain.xml 文件,該文件包含了跨域策略信息。比如最重要的一點,就是告訴Flash哪些域可以跨域請求該服務器。
舉個栗子,http://baidu.com/a.html下有某swf文件要向http://loliner.com/請求資源。此時會經過如下步驟:
Flash發現請求需要跨域,則首先請求http://loliner.com/crossdomai...文件;
若crossdomain.xml文件能正常返回,則分析其中的策略,查看本域是否合法;
若本域合法,則發送跨域請求;若不合法,則直接封殺請求。
此處注意,如果本域非法,Flash就會直接封殺了請求,那么我們在瀏覽器控制臺是捕獲不到該請求的,因為就沒發出去。
那么Flash是怎么判斷本域是否合法的呢?我們先來看一下一個最簡單的corssdomain.xml文件結構。
所有的 crossdomain.xml 都以
其中,鍵值 domain 表示允許跨域的源,此處就跟 CORS 的 Access-Control-Allow-Origin 字段一樣了。
而 secure ,則表示請求是否以加密進行傳輸。如果 corssdomain.xml 文件是從 https 協議下加載的,那么 secure 默認為 true。此時Flash若發現本域為非 https 協議,縱使 domain 合法,也會封殺請求。如果secure為false,則表明Flash可以發送非https加密過的請求。
Security.allowDomain 跨域權限授予如果說介紹 crossdomain.xml 文件時我們是以 Client 端為角度的,那么介紹 Security.allowDomain 則必須以 Server 作為角度。
你可能會遇到如下情形,開發了多個swf,它們之間相互依賴,但以不同的域發布到網上。此時你只希望某些特定的域才有權限去修改或調用該swf中的屬性及方法。那么此時,你就需要用到allowDomain方法對你所允許的域進行授權了。
以下是 allowDomain 的描述:
允許指定的域中的 SWF 文件訪問調用了此方法的 SWF 文件中的對象和變量。
再舉個栗子,http://a.com/a.swf 需要調用及修改 http://b.com/b.swf 中的屬性及方法。
那么,就必須在b.swf中調用 Security.allowDomain("a.com")以允許a.com域對自己進行訪問。
另外,要注意非常重要的一點,Security.allowDomain跨域權限授予是不對稱的。
也就是說,在上面的栗子中,只允許a.swf訪問b.swf,但b.swf卻不能夠訪問a.swf。
如果非要這樣做,那么就在a.swf中對b.com進行權限授予。
其次,對于HTTPS來說,即使調用了該方法,若試圖利用在HTTP下的swf去修改HTTPS下的swf,此時也是非法的。因為這本身就不安全。
如果非要這樣做,可以讓HTTPS下的swf調用Security.allowInsecureDomain()對HTTP域進行權限授予
跨域方式對比反觀 Flash 跨域與H5 CORS 跨域,雖然兩者在形式上有所不同,但本質上都向著以下兩個特點靠攏:
先詢問,后請求; 安全性靠Server端來維護。
對于 CORS 簡單請求來說,瀏覽器是不會進行預檢請求發送的,這樣一個請求搞定所有的事,卻不一定完全合理。因為對于瀏覽器來說,我在沒有知道Server是否認為我的請求合法前,就已經拋出了大量的查詢數據。這就有可能造成數據傳輸的冗余。
另外,如果由于開發過程不當,頻繁發送不合法的跨域請求,本身就是一個資源的浪費。
所以,才需要到復雜請求。
而對于 Flash crossdomain.xml 這種方式(與 CORS 復雜請求類似),就避免了頻繁發送不合法的跨域請求,因為在crossdomain.xml返回之前,Flash是不會發送任何跨域請求,直接在本地就將其封殺。同時crossdomain.xml并非每次跨域前都會請求,其有一個有效期。
但若我本身只需請求一次數據,但Server由于業務繁重卻給我返回一個龐大的crossdomain.xml,這反而又顯得不合理了。
文章來源:http://mp.weixin.qq.com/s/_KA...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/82857.html
摘要:上節我們講了同源策略,這節我們講講如何跨域。當這些從的腳本執行出錯,因為違背了同源策略為了保證用戶信息不被泄露,錯誤信息不會顯示出來,取而代之只會返回一個。 前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS),本著提升技術水平,打牢基礎知識的中心思想,我們開課啦(每...
摘要:需注意的是由于同源策略的限制,所讀取的為跨域請求接口所在域的,而非當前頁。目前,所有瀏覽器都支持該功能需要使用對象來支持,也已經成為主流的跨域解決方案。反向代理接口跨域跨域原理同源策略是瀏覽器的安全策略,不是協議的一部分。 什么是跨域? 跨域是指一個域下的文檔或腳本試圖去請求另一個域下的資源,這里跨域是廣義的。 廣義的跨域: 1.) 資源跳轉: A鏈接、重定向、表單提交 2.) 資源...
摘要:在接觸前端開發起,跨域這個詞就一直以很高的頻率在我們學習工作中重復出現,最近在工作中遇到了跨域的相關問題,這里我把它總結記錄一下。 在接觸前端開發起,跨域這個詞就一直以很高的頻率在我們學習工作中重復出現,最近在工作中遇到了跨域的相關問題,這里我把它總結記錄一下。關于跨域,有N種類型,現在我只專注于ajax請求跨域(ajax跨域只是屬于瀏覽器同源策略中的一部分,其它的這里不做介紹),內容...
閱讀 3486·2021-11-12 10:36
閱讀 2857·2021-09-22 15:35
閱讀 2807·2021-09-04 16:41
閱讀 1164·2019-08-30 15:55
閱讀 3574·2019-08-29 18:43
閱讀 2070·2019-08-23 18:24
閱讀 1412·2019-08-23 18:10
閱讀 1921·2019-08-23 11:31