同源策略
在客戶端程式語言中,如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
JSONP (JSON with Padding)是一個簡單且有效率的跨域方式,HTML中的script標籤可以載入並執行其他網域的JavaScript,所以我們可以透過script標記來動態載入其他網域的資源。例如我要從域A的頁面pageA加載域B的數據,那麼在域B的頁面pageB中我以JavaScript的形式聲明pageA需要的數據,然後在pageA中用script標籤把pageB加載進來,那麼pageB中的腳本就會得以執行。 JSONP在此基礎上加入了回呼函數,pageB載入完後會執行pageA中定義的函數,所需的資料會以參數的形式傳遞給函數。 JSONP易於實現,但是也會存在一些安全隱患,如果第三方的腳本隨意地執行,那麼它就可以篡改頁面內容,截獲敏感資料。但是在受信任的雙方傳遞數據,JSONP是非常合適的選擇。
Flash URLLoader
Flash有自己的一套安全策略,伺服器可以透過crossdomain.xml檔案來聲明能被哪些網域的SWF檔案訪問,SWF也可以透過API來決定自身能被哪些網域的SWF載入。當跨網域存取資源時,例如從網域www.a.com請求網域www.b.com上的數據,我們可以藉助Flash來傳送HTTP請求。首先,修改網域www.b.com上的crossdomain.xml(一般存放在根目錄,如果沒有需要手動建立) ,把www.a.com加入到白名單。其次,透過Flash URLLoader發送HTTP請求,最後,透過Flash API把回應結果傳遞給JavaScript。 Flash URLLoader是一種很普遍的跨網域解決方案,不過需要支援iOS的話,這個方案就無能為力了。
Access Control
Access Control是比較超越的跨域方式,目前只在很少的瀏覽器中得以支持,這些瀏覽器可以發送一個跨域的HTTP請求(Firefox, Google Chrome等透過XMLHTTPRequest實現,IE8下透過XDomainRequest實現),請求的回應必須包含一個Access-Control-Allow-Origin的HTTP回應頭,該回應頭聲明了請求網域的可存取權限。例如www.a.com對www.b.com下的asset.php發送了一個跨域的HTTP請求,那麼asset.php必須加入如下的回應頭:
header("Access-Control-Allow-Origin: http://www.a.com");