Angular經過CORS實現跨域方案

 之前有一篇很老的文章網上轉了不少,包括如今若是你百度"跨域"這個關鍵字,前幾個推薦的都是"Javascript跨域總結與解決方案".看了一下感受手段有點陳舊了,有一些好比document.domain還有iframe的解決方案委實"醜陋"一些,感受再也不適用於如今一些項目中.前端

    就拿iframe來講做爲一個前端工程師,我極爲討厭iframe這種東西.它不光增長了性能上的高負荷,同時也不利於掌控.ajax

    在Angular應用中實現跨域的方式相對簡單,基本上經過兩種方式便可.一種是JSONP,另外一種是經過CORS.前者是相對比較老的手法,後者我感受更加給力一點,因此本文主要說一下Angular如何與CORS配合跨域.json

    能不使用JSONP就儘可能不使用,這是着手於Angular跨域的一個原則吧.無論怎麼說,script的標籤嵌入感受仍是low了點.後端

    Angular推崇的時先後端分離,因此跨域由哪一方實現成爲一個問題.這個就不得不說前端技術上的侷限性,即便是相對好用的JSONP對於非GET請求也是無能爲力的,由於它本質上仍是經過script去get一些資源.api

    JSONP這種只能GET的限制,在Angular推崇RESTful風格接口的API場景下,就徹底制約了它的使用,總不能棄POST和PUT那些無論.而且JSONP的錯誤處理很弱,不盡人意.總以前端實現跨域都有各類各樣的侷限性,又好比像document.domain則只能用於主域相同,子域不一樣的狀況.跨域

    因此總結而言,雖然前端有多種方式處理跨域,可是多而不精,缺點都比較明顯.相對而言更好的方式是經過後端參與處理,這樣作不只適用性更強,同時前端只要發送正常的Ajax請求便可.這樣的技術叫作CORS.瀏覽器

    Cross-Origin Resource Sharing跨域資源共享,應該算是如今最爲推薦的跨域處理方案.不只適用於各類Method,並且更加方便和簡單.固然了,這麼吊的東西只有現代瀏覽器支持,IE8一下的老古董就不要想了.服務器

 

    CORS實現原理前端工程師

 

    雖然經過CORS實現跨域基本上徹底由後端實現,不過身爲一個給力的前端.仍是要掌握一下這一原理,以便當你遇到不靠譜的後端時,不至於...你懂得app

    CORS的本質讓服務器經過新增響應頭Access-Control-Allow-Origin,經過HTTP方式來實現資源共享,讓每一個請求的服務直接返回資源.它使用了HTTP交互方式來肯定請求源是否有資格請求該資源,而且經過設置HTTP Header來控制訪問資源的權限.

    具體的過程是這樣的前端發送一個正常的請求:

$http.get('www.cros.com/api/data',{params:{

  name: '頑Shi'

}})

    後端設置一下response的header:

 

Access-Control-Allow-Origin: "*"

Access-Control-Allow-Methods: "GET"

Access-Control-Max-Age: "60"   

    而後你觀察一下瀏覽器的行爲會發現有趣的事,瀏覽器在沒有你干預的狀況下,發現這是一個跨域請求.因此它沒有直接發送GET請求,而是發送了一個OPTIONS請求詢問是否能夠跨域訪問該資源,這個過程咱們能夠稱之爲"預檢".

    而後咱們看到OPTIONS的response返回了相似下面的信息:

HTTP/1.1 200 OK

 

Date: Mon, 01 Dec 2013 01:15:39 GMT

Server: Apache/2.0.61 (Unix)

Access-Control-Allow-Origin: *

Access-Control-Allow-Methods: GET

Access-Control-Max-Age: 60

Content-Encoding: gzip

Content-Length: 0

Connection: Keep-Alive

Content-Type: text/text

    這裏的這幾個Access頭的內容就是服務器後端加上去的,它告訴了瀏覽器此後的60秒內,全部域均可以經過GET方法進行跨域訪問該資源.而後瀏覽器自動再次發送了真正的GET請求,並返回對應的結果.

    注意這一過程是瀏覽器自動實現的,這一點是否是很是棒.一些header信息的設置以下:

Access-Control-Allow-Origin:| * // 受權的源控制

Access-Control-Max-Age:// 受權的時間

Access-Control-Allow-Credentials: true | false // 控制是否開啓與Ajax的Cookie提交方式

Access-Control-Allow-Methods:[,]* // 容許請求的HTTP Method

Access-Control-Allow-Headers:[,]* // 控制哪些header能發送真正的請求    

    這裏還有一處須要前端工程師協做的地方就是cookie的傳遞,默認狀況下經過CORS這樣的方式是不會傳遞cookie.通常強制性將cookie添加到header的作法,也會被瀏覽器拒絕並報錯.上面看到了在服務器端會經過添加一個response頭,Access-Control-Allow-Credentials來控制是否容許Cookie的提交.

    在Angular中咱們須要進行一些設置達到目的:

$http.post(url, {withCredentials: true, ...})

// 或者

$http({withCredentials: true, ...}).post(...)

// 或者

.config(function ($httpProvider) {

  $httpProvider.defaults.withCredentials = true;

}

    若是是jQuery則要設置以下:

$.ajax("www.cros.com/api/data", {

  type: "GET",

  xhrFields: {

    withCredentials: true

  },

  crossDomain: true,

  success: function(data, status, xhr) {

  }

});

    CORS的過程描述完畢,在網上找到一張圖片:

 

    CORS的分類

    若是仔細觀察瀏覽器的行爲會發現,並非全部的跨域請求都會發送OPTIONS請求.是否是有些奇怪,這就涉及到CORS的分類,簡單請求和複雜請求.

    HTTP的header一般包含下面這些內容:

Accept

Accept-Language

Content-Language

Last-Event-ID

Content-Type的值僅是下列之一:

                                              application/x-www-form-urlencoded

                                              multipart/form-data

                                              text/plain

    HTTP方法是HEAD,GET,POST之一,同時HTTP的header包含如上面所示.任何一個不知足這兩種要求的請求,都是複雜請求.好比發送PUT,DELETE等HTTP動做,或者Content-Type: application/json的內容.

    只有複雜請求包含"預檢"這一動做,另外Access-Control-Max-Age應該也會影響OPTIONS請求的發送.

相關文章
相關標籤/搜索