淺談CORS

淺談CORS

CORS全稱「跨站資源共享」(Cross-Origin Resource Sharing),它容許瀏覽器克服瀏覽器同源策略向跨域服務器發出請求。html

同源策略

概念

說到CORS,那麼就不得不提瀏覽器同源策略,所謂「同源」,是指服務器URL的三個相同:web

1.協議相同json

2.域名相同跨域

3.端口相同瀏覽器

舉個栗子:好比一個URL是http://www.example.com:80/a.html,那麼:緩存

http://www.example.com:80/b.html    // 同源
https://www.example.com:80/a.html   // 非同源(協議不一樣)
http://www.example1.com:80/a.html   // 非同源(域名不一樣)
http://www.example.com:81/a.html    // 非同源(端口不一樣)

限制

若是非同源,那麼三種行爲將受到限制:安全

1.非同源頁面沒法跨域讀取瀏覽器本地數據存儲(Cookie、LocalStorage和IndexDB)服務器

2.非同源頁面沒法跨域獲取DOMwebsocket

3.非同源頁面沒法跨域發送AJAX請求app

目的

那麼,爲何瀏覽器要使用同源策略?

同源策略的目的,是爲了保證用戶的信息安全,防止被不法分子竊取數據。而衆所周知,Cookie包含大量的登陸信息,若是一個網頁能夠跨域訪問另外一個網站的Cookie,那麼不法分子能夠經過使用跨域訪問獲取Cookie而後冒充用戶,隨心所欲。

因而可知,同源策略是極其有必要的。

突破同源策略

可是,不少時候,咱們須要跨域發送AJAX請求,此時咱們就須要突破同源策略不容許發送跨域AJAX的規定。隨着技術的發展,有不少技術能夠實現跨域發送AJAX請求,常見的有如下三種:

1.JSONP

2.Websocket

3.CORS

JSONP

JSONP是CORS技術出來以前最經常使用的跨域解決方案,最大的特定是兼容性好,簡單,不須要進行大的服務器改動。它的基本思路是經過動態添加一個script標籤,向服務器請求腳本,腳本中通常調用一個客戶端定義的函數,將數據做爲參數,調用客戶端的函數,而客戶端經過操做該函數,可使用被當作參數傳過來的數據。

由於服務器不限制script的跨域,因此不受跨域影響。

Websocket

衆所周知,Websocket是一個持久化協議,經常使用於解決服務器推送問題。可是,實際上Websocket其實支持跨域通訊。經過設置Websocket的origin的字段,能夠規定容許跨域的站點。

上面兩種方法雖然能夠解決跨域,可是,都有着各類問題。

慶幸的是,本文的主角:CORS的出現,完全解決了跨域問題。

CORS

瀏覽器將跨域AJAX請求分爲兩類:簡單請求和非簡單請求,對應有兩種不一樣的處理方式。

簡單請求

何爲簡單請求?

簡單請求就是知足如下兩個條件的請求:

1.請求方法爲HEAD、GET和POST

2.HTTP請求頭只包含:AcceptAccept-LanguageContent-LanguageLast-Event-ID以及值爲application/x-www-form-urlencodedmultipart/form-datatext/plain三者之一的Content-Type

對於簡單請求,瀏覽器能夠直接發送請求到服務器,可是會在請求頭中添加一個origin字段,該字段用來講明請求的來源。服務器會識別該字段,判斷是否容許跨域。

若是容許跨域,服務器會返回結果並在響應頭上添加三個字段:

1.Access-Control-Allow-Origin

該字段的值爲Origin字段的值,或者是*,表示服務器接受任何源的跨域請求。

2.Access-Control-Allow-Credentials

可選字段,它表示是否容許發送Cookie,值爲true時,表示發送請求的時候容許發送Cookie,若是不包含該字段,則表示不容許發送Cookie。

值得一提的是,若是服務器容許發送Cookie,那麼不容許將Access-Control-Allow-Origin的值設爲*

3.Access-Control-Expose-Headers

可選字段,在沒有該字段的狀況下,針對跨域請求,XHR對象的getResponseHeader()方法只能拿到Cache-ControlContent-LanguageContent-TypeExpireLast-ModifiedPragma這六個字段,該字段能夠設置額外能夠拿到的字段。

非簡單請求

不知足簡單請求的跨域請求都是非簡單請求,好比PUT或DELETE方法。

不一樣於簡單請求的直接向服務器請求,非簡單請求會在發送以前,先進行一次「預檢」(preflight),即,向服務器發出一個OPTIONS請求,查詢服務器是否容許它進行跨域請求。

若是服務器不經過「預檢」,會返回一個error,客戶端能夠經過onerror事件進行捕獲。

當服務器經過「預檢」後,服務器會進行響應,響應頭中含有CORS的相關字段,分別是:

1.Access-Control-Allow-Origin

該字段和簡單請求中的同名字段同樣。

2.Access-Control-Allow-Methods

該字段表示服務器支持跨域的全部方法,是一個逗號分隔的字符串,如:POST,DELETE。

3.Access-Control-Allow-Headers

該字段表示服務器支持的全部頭信息,也是一個逗號分隔的字符串。

4.Access-Control-Allow-Credentials

可選字段,與簡單請求中的同名字段同樣。

5.Access-Control-Max-Age

可選字段,在一段時間內,瀏覽器對同一個域名進行非簡單跨域請求,只對第一次進行「預檢」,而這一次「預檢」的結果將被緩存,接下來的請求都經過該結果進行判斷。該字段就是用來設置「預檢」結果緩存的時間長短,能夠將其值設爲-1來禁用「預檢」緩存。

接收到服務器經過「預檢」的響應後,客戶端會正式發送真正的請求,接下來的處理方式和簡單請求一致。

總結

在當前開發中,當不須要兼容老式瀏覽器中,咱們通常採用CORS的方式進行跨域請求,由於相比Websocket,CORS支持非長鏈接場景;相比JSONP,CORS支持全部HTTP請求,用法更加平滑。

固然,值得一提的是,當你須要兼容老式瀏覽器時,JSONP是你惟一的選擇~

相關文章
相關標籤/搜索