關於跨域的幾種解決方案

在前後端交互的過程當中,跨域是一個老生常談的問題了,說說自己的一些理解。

什麼時候會發生跨域現象?

跨域的產生,是由於同源策略的限制,xhr或者fetch這樣的API都遵循這個策略,所以當我們在某個域的頁面,比如 http://kasol.com,他通過xhr發起一個請求,指向http://aenvgiell.com,那麼這個時候就會產生跨域現象,得不到想要的內容。需要注意的是,其實對於服務端來說,此時的通信是正常的,服務端的邏輯照樣執行,也會正常發送響應,但是在瀏覽器端卻被阻斷了

怎麼來解決跨域?

  1. 最通用的方案要屬jsonp了,實際上這不是一個官方的解決方法,但是卻應用十分廣泛。剛剛說,使用xhr的方式跨域訪問資源會被攔截,但是其實在前端要發起請求是有很多方法的,比如style標籤,script標籤,img標籤,他們都可以發起一個請求,那麼我們用一個script標籤,把src指向一個跨域的路由
<script src="http://aenvgiell.com/list/get?callback=printList"></script>

此時這個請求就可以正常返回內容了,由於一般情況下,我們會在script標籤裏面指向一個靜態JS文件,所以這種用法不太常用,但是這個就是jsonp的原理,假如後端的這個路由是這樣處理的

// 僞代碼
var list = getListFromDB();
var callback = ctx.query.callback;
response.write( callback(list));

大概的意思,就是獲取到此次目標的資源,也就是list,然後把前端帶過來的參數,當做一個函數名,然後返回一個函數的調用給前端。所以這段代碼到了前端之後,應該是這樣的

<script>
    printList(list)
</script>

所以我們需要在這個腳本執行前,先定義一個名稱爲printList的函數

function printList(list){
	console.log(list);
}

這樣一來,跨域的資源就可以被我們使用了,很多庫比如Jquery已經統一封裝了這類請求。注意,這種請求回來的內容瀏覽器不會攔截掉,所以可以通過這種方式順利的拿到非同源的資源。但是實際上, 從上面可以看到,這種方式需要前後端同學一起配合,但是比如前後端都是一個人來開發的話,就會省去一些溝通成本。並且這種方式只支持GET請求,原因也很明顯。
我們剛纔說的這個方法,是基於script標籤發出的跨域請求不會被攔截而實現的,但是有時候我們也有方式讓瀏覽器可以攔截這種請求內容,詳細可以瞭解一下CORB,關於X-Content-Type-Options這個響應頭的信息。

  1. 還有一種比較常用的方式,即CORS。實際上,資源是放在跨域的服務端上,假如我要申請訪問那個資源,只要那個跨域的服務端同意即可,所以服務端需要在響應頭上設置好響應頭: access-control-allow-origin
    可以給他設置爲通配符*,也可以多個域名,需要注意的是,假如需要驗證用戶信息比如cookie時,即前端指定了withCredentials爲true,那麼此時不能使用通配符,要指定對應域名。這種方式也要服務端的配合。可以看看MDN上關於CORS的詳細說明 。
    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

  2. 通過服務端代理的方式來獲取跨域的資源,上面提到過,跨域其實是瀏覽器攔截的請求內容,但是在服務端通過http或者rpc的方式是完全可以訪問到的,所以可以這麼做

xhr.open("http://kasol.com/list/proxy","GET");
xhr.send();

然後服務端處理

var ret = httpRequest.get("http://aenvgiell.com/list/get");
ctx.body = ret;

這樣一來,也可以拿到這個資源。只不過服務端要改動的多一些

其他

其實最主流的就是上面提到的這些方式,不過還有一些比較少見的方法,這裏提一下,不詳細說明,有興趣的話可以自行搜索。

更改瀏覽器的打開方式,上面提到, 跨域是瀏覽器的限制,但是我們實際上在運行瀏覽器時,可以用其他方式打開,平常我們是用點擊圖標這種方法打開,實際上可以通過cmd的方式,附帶一些設置信息來打開瀏覽器,這些設置的意圖就是告訴瀏覽器,不要去攔截跨域的請求內容,平常我們在開發調試的時候這招有些用武之地,但是對於一般用戶來說,不太適用。

通過Adobe Flash,運行在瀏覽器的腳本除了JavaScript之外,還有一個叫ActionScript,這東西依賴flash player,運行在fvm這個容器裏面,類似於jvm,他也有類似於xhr一樣的API,被稱爲HTTPService,他可以通過配置文件的方式,來成功訪問到跨域的資源,並且它提供了對應的類來和JavaScript通信,所以這種方式也能解決跨域問題,但是看得出來,非常繁瑣,而且Adobe FLex也漸漸的開始退出歷史舞臺。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章