cors 跨域資源共享 Cross-origin resource sharing是一種跨域的解決方案 它容許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。 可是須要瀏覽器的支持。
值得注意的是:
整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於開發者來講,CORS通訊(只要在服務器端設置了就行)與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏覽器一旦發現是cors狀況的AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。html
瀏覽器將cors請求分爲兩類:簡單請求 非簡單請求。
簡單請求同時知足如下兩個要求:json
(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
不可以同時知足以上兩個條件的請求就是非簡單請求。api
對於簡單請求,瀏覽器直接發出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 //可選的 一、 Content-Type: text/html; charset=utf-8
一、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;
若是在服務器返回的響應中沒有以上的字段 就說明此次跨域是不成功的。cookie
非簡單請求是那種對服務器有特殊要求的請求,好比請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json。
下面是就是一個非簡單請求。app
var url = 'http://api.alice.com/cors'; var xhr = new XMLHttpRequest(); xhr.open('PUT', url, true); xhr.setRequestHeader('X-Custom-Header', 'value'); xhr.send();
非簡單請求的CORS請求,會在正式通訊以前,增長一次HTTP查詢請求,稱爲"預檢"請求(preflight)。
瀏覽器首先發送請求詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及能夠使用哪些HTTP動詞和頭信息字段。只有獲得確定答覆,瀏覽器纔會發出正式的XMLHttpRequest請求,不然就報錯。
瀏覽器發送一個非簡單請求以前,就自動發出一個"預檢"請求,要求服務器確承認以這樣請求。下面是這個"預檢"請求的HTTP頭信息。cors
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
一旦服務器經過了"預檢"請求,之後每次瀏覽器正常的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
JSONP只支持GET請求,CORS支持全部類型的HTTP請求。JSONP的優點在於支持老式瀏覽器,以及能夠向不支持CORS的網站請求數據。