面試--跨域--cors

cors是什麼

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簡單請求

對於簡單請求,瀏覽器直接發出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

瀏覽器發送非簡單cors請求

非簡單請求是那種對服務器有特殊要求的請求,好比請求方法是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

cors和JSONP的比較

JSONP只支持GET請求,CORS支持全部類型的HTTP請求。JSONP的優點在於支持老式瀏覽器,以及能夠向不支持CORS的網站請求數據。

相關文章
相關標籤/搜索