1. 程式人生 > >跨域CORS的情緣~

跨域CORS的情緣~

文章主要內容來自這篇文章

cors:完成資源的跨域訪問 。

相同的協議,主機地址以及埠號才能夠進行訪問。

業界中提出了一些解決該問題的方法:domian屬性,跨文件訊息,JSONP,以及CORS等~

方案各有長處,根據不同的需求來對方案選擇。

domain

直接快速的方法,較為常見。不同域中得到指令碼的domain屬性設定為同一值,就能使這些指令碼進行互動。

document.domain="icodehub.cn";

 跨文件的訊息

通過向window例項傳送訊息來完成的。在使用時,呼叫postMessage()函式傳送訊息。window內部的onmessage事件被觸發,進而該事件的訊息處理函式被呼叫。訊息處理函式首先需要判斷訊息來源的合法性,以避免惡意使用者通過傳送訊息的方法來非法執行程式碼。

JSONP

通過script標籤來從另一個域中返回資料。

<script src="http://www.icodehub.cn?callback=some_func"></script>

會指向http://www.icodehub.cn傳送一個GET請求,在資料返回客戶端,some_func函式會被呼叫。只支援GET。

CORS

Simple Request

想象想別的域傳送請求:

function retrieveData() {
     var request = new XMLHttpRequest();
     request.open('GET', 'http://public-data.com/someData', true);
     request.onreadystatechange = handler;
     request.send();
}

支援cors協議的服務會給出響應:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.icodehub.cn
Content-Type: application/xml

有一個響應頭Access-Control-Allow-Origin。用來記錄可以訪問該資源的域。

在接收到服務端響應後,瀏覽器檢視響應中是否包含Access-Control-Allow-Origin。

如果存在,瀏覽器將會分析該響應頭中所標示內容。如果包含了當前頁面所在的域,那麼瀏覽器將知道允許跨域訪問。

CORS則將導致跨域訪問的請求分為三種:Simple Request,Preflighted Request以及Request with Credential。

如果一個請求沒有包含任何自定義的請求頭,所使用的HTTP動詞是GET,HEAD,POST之一,那麼他就是Simple Request。但是POST作為請求動詞時centent-type需要設定:application/x-www-form-urlencoded,multipart/form-data或text/plain之一。

如果包含了自定義的請求頭,或者他使用的HTTP動詞時HEAD,GET,POST之外的,那麼就是Preflighted Request。如果POST請求的content-type並不是application/x-www-form-urlencoded,multipart/form-data或text/plain之一,那麼也是Preflighted Request。

一般情況下,一個跨域請求不會包含當前頁面的使用者憑證。

跨域包含了當前頁面的憑證,其屬於Request with Credential。

Preflighted Request

傳送一個post請求:

 function sendData() {
     var request = new XMLHttpRequest(),
         payload = ......;
     request.open('POST', 'http://public-data.com/someData', true);
     request.setRequestHeader('X-CUSTOM-HEADER', 'custom_header_value');
     request.onreadystatechange = handler;
     request.send(payload);
 }

首先發出的並不是post請求,而是option請求。該請求通過Access-Control-Request-Method以及Access-Control-Request-Headers標示了請求型別以及請求中所包含的自定義HTTP Header。進行訪問資源前傳送一個請求進行探測。

 HTTP/1.1 200 OK
 Access-Control-Allow-Origin: http://ambergarden.com
 Access-Control-Allow-Methods: POST, GET, OPTIONS
 Access-Control-Allow-Headers: X-CUSTOM_HEADER
 Access-Control-Max-Age: 1728000

瀏覽器分析響應並瞭解到其被允許向服務端傳送資料以後,才會傳送真正的POST請求。

服務端則會接受並處理請求。

Request with Credential

在傳送請求的時候,需要將使用者憑證包含在請求內。

function retrieveData() {
     var request = new XMLHttpRequest();
     request.open('GET', 'http://public-data.com/someData', true);
     request.withCredentials = true;
     request.onreadystatechange = handler;
     request.send();
}

服務端的響應中,其將擁有一個額外的Access-Control-Allow-Credentials響應頭。

整合CORS支援,使用cors來訪問資料時候不需要做任何資料訪問邏輯的更改,所有的工作都是服務端以及瀏覽器間自動完成。主要的工作在服務端,需要進行配置。