cors是什么
cors 跨域資源共享 Cross-origin resource sharing是一種跨域的解決方案 它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。 但是需要瀏覽器的支持。
值得注意的是:
整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對于開發者來說,CORS通信(只要在服務器端設置了就行)與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現是cors情況的AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。
瀏覽器對跨域資源請求的分類
瀏覽器將cors請求分為兩類:簡單請求 非簡單請求。
簡單請求同時滿足以下兩個要求:
(1) 請求方法是以下三種方法之一:
HEAD
GET
POST
(2)HTTP的頭信息不超出以下幾種字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
不能夠同時滿足以上兩個條件的請求就是非簡單請求。
瀏覽器發起cors簡單請求
對于簡單請求,瀏覽器直接發出CORS請求。具體來說,就是在頭信息之中,增加一個Origin字段。如下就是一個瀏覽器發簡單請求的 請求報文的頭部信息
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
上面的頭信息中,Origin字段用來說明,本次請求來自哪個源(協議 + 域名 + 端口)。本實例中請求是來自 http://api.bob.com 服務器根據這個值,決定是否同意這次請求。
如果Origin指定的域名在許可范圍內,服務器返回的響應,會多出幾個頭信息字段。
Access-Control-Allow-Origin: http://api.bob.com //必須的 請求時Origin值或者一個*
Access-Control-Allow-Credentials: true //可選的 服務器許可請求中可有Cookie,一起發給服務器。
Access-Control-Expose-Headers: FooBar //可選的 1、
Content-Type: text/html; charset=utf-8
1、XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值
瀏覽器發起簡單cors請求的時候自動發送cookie
瀏覽器發送CORS請求是默認不發送Cookie和HTTP認證信息
如果要把Cookie發到服務器,
一方面要服務器同意,指定Access-Control-Allow-Credentials字段。
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
如果在服務器返回的響應中沒有以上的字段 就說明這次跨域是不成功的。
瀏覽器發送非簡單cors請求
非簡單請求是那種對服務器有特殊要求的請求,比如請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json。
下面是就是一個非簡單請求。
var url = 'http://api.alice.com/cors';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();
發起非簡單請求有如下步驟
1、 預檢請求
非簡單請求的CORS請求,會在正式通信之前,增加一次HTTP查詢請求,稱為"預檢"請求(preflight)。
瀏覽器首先發送請求詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答復,瀏覽器才會發出正式的XMLHttpRequest請求,否則就報錯。
瀏覽器發送一個非簡單請求之前,就自動發出一個"預檢"請求,要求服務器確認可以這樣請求。下面是這個"預檢"請求的HTTP頭信息。
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
"預檢"請求用的請求方法是OPTIONS,表示這個請求是用來詢問服務器支持什么請求方法的。
"預檢"請求的頭信息包括兩個特殊字段。
(1)Access-Control-Request-Method
該字段是必須的,用來列出瀏覽器的CORS請求會用到哪些HTTP方法,上例是PUT。
(2)Access-Control-Request-Headers
該字段是一個逗號分隔的字符串,指定瀏覽器CORS請求會額外發送的頭信息字段,上例是X-Custom-Header。
服務器返回的針對預檢請求的響應
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com //表示哪個源可以跨域請求資源 origin的值或者*
Access-Control-Allow-Methods: GET, POST, PUT //服務器支持的所有跨域請求的方法
Access-Control-Allow-Headers: X-Custom-Header //服務器支持的所有頭信息字段
Content-Type: text/html; charset=utf-8 //可選的 服務器許可請求中可有Cookie,一起發給服務器。
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
2、 瀏覽器的正常請求和回應
一旦服務器通過了"預檢"請求,以后每次瀏覽器正常的CORS請求,就都跟簡單請求一樣,會有一個Origin頭信息字段。服務器的回應,也都會有一個Access-Control-Allow-Origin頭信息字段。
下面是正常的cors的http請求頭部信息
PUT /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
下面是服務器的正常響應
Access-Control-Allow-Origin: http://api.bob.com
Content-Type: text/html; charset=utf-8
cors和JSONP的比較
JSONP只支持GET請求,CORS支持所有類型的HTTP請求。JSONP的優勢在于支持老式瀏覽器,以及可以向不支持CORS的網站請求數據。