跨域訪問和防盜鏈基本原理(二)

發表於2015-10-18

二、跨域訪問基本原理

在上一篇,介紹了盜鏈的基本原理和防盜鏈的解決方案。這裡更深入分析一下跨域訪問。先看看跨域訪問的相關原理:跨網站指令碼。維基上面給出了跨站訪問的危害性。從這裡可以整理出跨站訪問的定義:JS指令碼在瀏覽器端發起的請求其他域(名)下的網站資料的HTTP請求。

這裡要與referer區分開,referer是瀏覽器的行為,所有瀏覽器發出的請求都不會存在安全風險。而由網頁載入的指令碼發起請求則會不可控,甚至可以截獲使用者資料傳輸到其他站點。referer方式拉取其他網站的資料也是跨域,但是這個是由瀏覽器請求整個資源,資源請求到後,客戶端的指令碼並不能操縱這份資料,只能用來呈現。但是很多時候,我們都需要發起請求到其他站點動態獲取資料,並將獲取到底資料進行進一步的處理,這也就是跨域訪問的需求。

 

現在從技術上有幾個方案去解決這個問題。

1、JSONP跨域訪問

利用瀏覽器的Referer方式載入指令碼到客戶端的方式。以:

這種方式獲取並載入其他站點的JS指令碼是被允許的,載入過來的指令碼中如果有定義的函式或者介面,可以在本地使用,這也是我們用得最多的指令碼載入方式。但是這個載入到本地指令碼是不能被修改和處理的,只能是引用。

而跨域訪問需要正是訪問遠端抓取到的資料。那麼能否反過來,本地寫好一個資料處理函式,讓請求服務端幫助完成呼叫過程?JS指令碼允許這樣。

遠端的伺服器上面定義的remote.js是這樣的:

上面首先在本地定義了一個函式localHandler,然後遠端返回的JS的內容是呼叫這個函式,返回到瀏覽器端執行。同時在JS內容中將客戶端需要的資料返回,這樣資料就被傳輸到了瀏覽器端,瀏覽器端只需要修改處理方法即可。這裡有一些限制:1、客戶端指令碼和服務端需要一些配合;2、呼叫的資料必須是json格式的,否則客戶端指令碼無法處理;3、只能給被引用的服務端網址傳送get請求。

服務端的PHP函式可能是這樣的:

這樣即可根據客戶端指定的回撥拼裝呼叫過程。

2、CORS(Cross-origin resource sharing)跨域訪問

上述的JSONP由於有諸多限制,已經無法滿足各種靈活的跨域訪問請求。現在瀏覽器支援一種新的跨域訪問機制,基於服務端控制訪問許可權的方式。簡而言之,瀏覽器不再一味禁止跨域訪問,而是需要檢查目的站點返回的訊息的頭域,要檢查該響應是否允許當前站點訪問。通過HTTP頭域的方式來通知瀏覽器:


服務端利用這幾個HTTP頭域通知瀏覽器該資源的訪問許可權資訊。在訪問資源前,瀏覽器會先發出OPTIONS請求,獲取這些許可權資訊,並比對當前站點的指令碼是否有許可權,然後再將實際的指令碼的資料請求發出。發現許可權不允許,則不會發出請求。邏輯流程圖為:

瀏覽器也可以直接將GET請求發出,資料和許可權同時到達瀏覽器端,但是資料是否交給指令碼處理需要瀏覽器檢查許可權對比後作出決定。

一次具體的跨域訪問的流程為:

因此許可權控制交給了服務端,服務端一般也會提供對資源的CORS的配置。

跨域訪問還有其他幾種方式:本站服務端代理、跨子域時使用修改域標識等方法,但是應用場景的限制更多。目前絕大多數的跨域訪問都由JSONP和CORS這兩類方式組成。

相關文章