JavaScript的10種跨域共用的方法總結

來源:互聯網
上載者:User

JavaScript出於安全方面的考慮,不允許跨域調用其他頁面的對象。跨域就是因為JavaScript同源策略的限制。在用戶端程式設計語言中,如javascript和ActionScript,同源策略是一個很重要的安全理念,它在保證資料的安全性方面有著重要的意義。同源策略規定跨域之間的指令碼是隔離的,一個域的指令碼不能訪問和操作另外一個域的絕大部分屬性和方法。下面讓我們共同學習一下跨越共用的方法。

同源策略

在用戶端程式設計語言中,如javascript和ActionScript,同源策略是一個很重要的安全理念,它在保證資料的安全性方面有著重要的意義。同源策略規定跨域之間的指令碼是隔離的,一個域的指令碼不能訪問和操作另外一個域的絕大部分屬性和方法。那麼什麼叫相同域,什麼叫不同的域呢?當兩個域具有相同的協議(如http),相同的連接埠(如80),相同的host(如www.example.org),那麼我們就可以認為它們是相同的域。比如http://www.example.org/index.html和http://www.example.org/sub/index.html是同域,而http://www.example.org,https://www.example.org,http://www.example.org:8080,http://sub.example.org中的任何兩個都將構成跨域。同源策略還應該對一些特殊情況做處理,比如限制file協議下指令碼的存取權限。本地的HTML檔案在瀏覽器中是通過file協議開啟的,如果指令碼能通過file協議訪問到硬碟上其它任意檔案,就會出現安全隱患,目前IE8還有這樣的隱患。

受到同源策略的影響,跨域資源共用就會受到制約。但是隨著人們的實踐和瀏覽器的進步,目前在跨域請求的技巧上,有很多寶貴經驗的沉澱和積累。這裡我把跨域資源共用分成兩種,一種是單向的資料請求,還有一種是雙向的訊息通訊。接下來我將羅列出常見的一些跨域方式,以下跨域執行個體的原始碼可以從這裡獲得。

單向跨域

JSONP(JSONwithPadding)是一個簡單高效的跨域方式,HTML中的script標籤可以載入並執行其他域的javascript,於是我們可以通過script標記來動態載入其他域的資源。例如我要從域A的頁面pageA載入域B的資料,那麼在域B的頁面pageB中我以JavaScript的形式聲明pageA需要的資料,然後在pageA中用script標籤把pageB載入進來,那麼pageB中的指令碼就會得以執行。JSONP在此基礎上加入了回呼函數,pageB載入完之後會執行pageA中定義的函數,所需要的資料會以參數的形式傳遞給該函數。JSONP易於實現,但是也會存在一些安全隱患,如果第三方的指令碼隨意地執行,那麼它就可以篡改頁面內容,截獲敏感性資料。但是在受信任的雙方傳遞資料,JSONP是非常合適的選擇。

flash有自己的一套安全性原則,伺服器可以通過crossdomain.xml檔案來聲明能被哪些域的SWF檔案訪問,SWF也可以通過API來確定自身能被哪些域的SWF載入。當跨域訪問資源時,例如從域www.a.com請求域www.b.com上的資料,我們可以藉助flash來發送HTTP請求。首先,修改域www.b.com上的crossdomain.xml(一般存放在根目錄,如果沒有需要手動建立),把www.a.com加入到白名單。其次,通過FlashURLLoader發送HTTP請求,最後,通過FlashAPI把響應結果傳遞給JavaScript。FlashURLLoader是一種很普遍的跨域解決方案,不過需要支援iOS的話,這個方案就無能為力了。

window對象的name屬性是一個很特別的屬性,當該window的location變化,然後重新載入,它的name屬性可以依然保持不變。那麼我們可以在頁面A中用iframe載入其他域的頁面B,而頁面B中用JavaScript把需要傳遞的資料賦值給window.name,iframe載入完成之後,頁面A修改iframe的地址,將其變成同域的一個地址,然後就可以讀出window.name的值了。這個方式非常適合單向的資料請求,而且協議簡單、安全。不會像JSONP那樣不做限制地執行外部指令碼。

在資料提供方沒有提供對JSONP協議或者window.name協議的支援,也沒有對其它域開放存取權限時,我們可以通過serverproxy的方式來抓取資料。例如當www.a.com域下的頁面需要請求www.b.com下的資源檔asset.txt時,直接發送一個指向www.b.com/asset.txt的Ajax請求肯定是會被瀏覽器阻止。這時,我們在www.a.com下配一個代理,然後把Ajax請求綁定到這個代理路徑下,例如www.a.com/proxy/,然後這個代理髮送HTTP請求訪問www.b.com下的asset.txt,跨域的HTTP請求是在伺服器端進行的,用戶端並沒有產生跨域的Ajax請求。這個跨域方式不需要和目標資源簽訂協議,帶有侵略性,另外需要注意的是實踐中應該對這個代理實施一定程度的保護,比如限制他人使用或者使用頻率。

雙向跨域

通過修改document的domain屬性,我們可以在域和子域或者不同的子域之間通訊。同域策略認為域和子域隸屬於不同的域,比如www.a.com和sub.a.com是不同的域,這時,我們無法在www.a.com下的頁面中調用sub.a.com中定義的JavaScript方法。但是當我們把它們document的domain屬性都修改為a.com,瀏覽器就會認為它們處於同一個域下,那麼我們就可以互相調用對方的method來通訊了。

不同的域之間,JavaScript只能做很有限的訪問和操作,其實我們利用這些有限存取權就可以達到跨域通訊的目的了。FIM(FragmentIdentitierMessaging)就是在這個大前提下被發明的。父視窗可以對iframe進行URL讀寫,iframe也可以讀寫父視窗的URL,URL有一部分被稱為frag,就是#號及其後面的字元,它一般用於瀏覽器錨點定位,Server端並不關心這部分,應該說HTTP請求過程中不會攜帶frag,所以這部分的修改不會產生HTTP請求,但是會產生瀏覽器記錄。FIM的原理就是改變URL的frag部分來進行雙向通訊。每個window通過改變其他window的location來發送訊息,並通過監聽自己的URL的變化來接收訊息。這個方式的通訊會造成一些不必要的瀏覽器記錄,而且有些瀏覽器不支援onhashchange事件,需要輪詢來獲知URL的改變,最後,URL在瀏覽器下有長度限制,這個制約了每次傳送的資料量。

頁面上的雙向通訊也可以通過Flash來解決,FlashAPI中有LocalConnection這個類,該類允許兩個SWF之間通過進程通訊,這時SWF可以播放在獨立的FlashPlayer或者AIR中,也可以嵌在HTML頁面或者是PDF中。遵循這個通訊原則,我們可以在不同域的HTML頁面各自嵌套一個SWF來達到相互傳遞資料的目的了。SWF通過LocalConnection交換資料是很快的,但是每次的資料量有40kb的大小限制。用這種方式來跨域通訊過於複雜,而且需要了2個SWF檔案,實用性不強。

window.postMessage是HTML5定義的一個很新的方法,這個方法可以很方便地跨window通訊。由於它是一個很新的方法,所以在很舊和比較舊的瀏覽器中都無法使用。

總的來說,跨域的方法有很多,我們可以針對不同的應用情境找到最合適的解決方案。比如單向的資料請求,我們應該優先選擇JSONP或者window.name,雙向通訊我們採取CrossFrame,在未與資料提供方沒有達成通訊協定的情況下我們也可以用serverproxy的方式來抓取資料。

【編輯精選】

  1. 如何在JavaScript中處理大量資料
  2. 8個令人驚歎的JavaScript效果的網站
  3. 對JavaScript中call和apply的理解
  4. 16款最流行的JavaScript架構
【責任編輯:QiHappy TEL:(010)68476606】


相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。