[HTTP趣談]支持跨域及相關cookie設置

[HTTP趣談]支持跨域及相關cookie設置

如今“前後端分離”的設計思想已經非常普及,所以一旦靜態資源和後臺應用部署在不同服務器上並採用不同域名,那麼,必然會遇到“瀏覽器同源策略”的限制,也必然,需要前後臺一起合作解決跨域問題。

1. 同源策略

什麼樣的URL是同源的?其必須滿足下面三個條件:

  • 協議號相同
  • 域名相同
  • 端口相同

比如,a.com網站,想要訪問b.com網站api,比如api.b.com。那麼,在“同源策略”限制下,a.com網站無法獲取api.b.com下的cookie,也無法向api.b.com發送ajax請求。

2. 如何支持跨域

最簡單的方式是後臺服務器將允許跨域訪問的URL添加到白名單中,這樣,前臺應用不需要做任何特殊處理。

另外,還有兩種常用方法:

1) JSONP

基本思想爲:網頁通過添加一個

<body>
<button onclick="loadData()">LoadData</button>
<script>
    function foo(res){
        console.log(res)
    }

    function loadData(){
        var elem = document.createElement('script');
        elem.src = 'http://a.com/jsonp?callback=foo';
        document.head.appendChild(elem);
    }
</script>
</body>

用JSONP,瀏覽器會自動在request header裏面帶上a.com下的cookie信息。
其實,通過src調用api都是GET方式,類似請求資源文件,必須明確,從Web頁面產生的文件請求都會帶上cookie

因此,JSONP的缺點很明顯了:

  • 只支持GET請求
  • 只能帶本域下的cookies
2) CORS(Cross-origin resource sharing)

CORS是一個W3C標準,全稱是”跨域資源共享”。它運行瀏覽器向跨域服務器發送AJAX請求。

小貼士

IE10以上用XMLHttpRequest對象實現CORS;
IE8,IE9用XDomainRequest支持CORS。

整個CORS跨域,是瀏覽器自動完成,不需要前端特殊處理。瀏覽器一旦發現是AJAX請求跨域,會添加origin頭信息,後臺應用需要根據request header中的origin/referer,來設置正確的response header,完成跨域請求。

img

cors.png

CORS具體的概念和講解,網上很多資料,包括什麼是簡單請求和“Preflighted”,請參考 https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

下面要重點提到的是,CORS下,前端如何攜帶cookies?

Requests with credentials

用JS/JQuery啓動AJAX請求時,必須設置withCredentials頭爲true,寫法如下:

JS:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('POST', ‘a.com’, true);
xhr.send();

JQuery:
$.ajax({
  url: a_cross_domain_url,
  xhrFields: {
    withCredentials: true
  }
});

這時,後臺設置response header時,需要返回:

Access-Control-Allow-Credentials: true;
Access-Control-Allow-Origin: a.com; //必須爲具體域名,不能是*

重點需要注意的是cookies信息!!!這時,request請求中可以攜帶的cookies,不僅僅有本域下的cookies,還包括跨域服務器下設置的cookies(注意:跨域服務器下的cookies,是無法通過JS代碼document.cookie訪問,該cookies只能被遠程服務器控制)。

可見,在安全性上,CORS比JSONP強悍很多!

CORS缺點是,低版本的IE瀏覽器支持不好。

3. 小結

針對iframe,還有些特殊的解決跨域方式,比如HTML5新特性:postMessage。
如果父子窗口是同一個主域,不同子域,也可以通過設置document.domain屬性,規避同源策略。

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