基本概念部分(一):理解CORS

說道Vue的跨域AJAX,我想先梳理一遍CORS跨域,"跨域資源共享"(Cross-origin resource sharing),它是一個(gè)W3C標(biāo)準(zhǔn)。

CORS跨域的特點(diǎn):它需要服務(wù)器的‘配合’。就是說,它的實(shí)現(xiàn)是:瀏覽器(所有瀏覽器和IE10+)+服務(wù)器。

一般情況下,我們可以在請(qǐng)求頭信息中加入Origin,來告知服務(wù)器自己來自哪個(gè)源:協(xié)議 + 域名 + 端口。如果Origin域名在指定許可范圍內(nèi),則服務(wù)器的響應(yīng)頭會(huì)多出三個(gè)信息:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動(dòng)畫培訓(xùn)

Access-Control-Allow-Origin:
//它的值,可以使一個(gè) *,表示接受所有域名的請(qǐng)求;還可以是指定的一個(gè)域名(在請(qǐng)求時(shí)就已經(jīng)寫好的那個(gè)origin域名)。Access-Control-Allow-Credentials:
//它的值為:true。他表示是否允許發(fā)送cookie,因?yàn)閏ookie不包含在CORS中,只有其值設(shè)為true時(shí),可以讓Cookie包含在請(qǐng)求中一起發(fā)給服務(wù)器。Access-Control-Expose-Headers:
//他表示XMLHttpRequest對(duì)象的getResponseHeader()方法的六個(gè)基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。(這里我用的最多的是Content-Type)

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動(dòng)畫培訓(xùn)

這里有一個(gè)withCredentials屬性需要我們知道。

因?yàn)镃ORS請(qǐng)求默認(rèn)不發(fā)送Cookie和HTTP認(rèn)證信息,因此需要 Access-Control-Allow-Credentials:true; 并且專門設(shè)置AJAX請(qǐng)求:(這里在Vue中有應(yīng)用,下面會(huì)說)

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

這樣才可以讓瀏覽器同意發(fā)送Cookie,配合服務(wù)器的需求和配置。

CORS還有一種情況是發(fā)送“預(yù)檢請(qǐng)求”。他會(huì)在正真的數(shù)據(jù)請(qǐng)求之前,先發(fā)送一次HTTP請(qǐng)求。瀏覽器會(huì)先詢問服務(wù)器自己的域名是否被許可,以及一些必要的頭部字段信息。服務(wù)器進(jìn)行回復(fù)后,瀏覽器再發(fā)送一次,這次是正式的 XMLHttpRequest 請(qǐng)求。

這里面說到的“預(yù)檢”請(qǐng)求的方法為options方法,表示說:“我是來詢問的”。因此當(dāng)我們?cè)贑hrome的開發(fā)者工具中會(huì)看到這個(gè)一串請(qǐng)求行:

OPTIONS /cors HTTP/1.1

對(duì)于這一點(diǎn)的應(yīng)用我的項(xiàng)目中主要是當(dāng) Content-Type 為 application/json的時(shí)候,其他的put或者delete也會(huì)有這樣的請(qǐng)求方式。

總的來說只是一個(gè)對(duì)CORS的梳理,并沒有很細(xì)致的解釋。它與JSONP的不同為JSONP只有g(shù)et請(qǐng)求可以跨域,而CORS支持所有的請(qǐng)求方式。雖然JSONP對(duì)老的瀏覽器支持比較好,但現(xiàn)在開發(fā)項(xiàng)目的瀏覽器大多較新,我也就更多的關(guān)注了CORS。

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動(dòng)畫培訓(xùn)

基本概念部分(二):理解 form data 和 request payload

在W3C中,<form>標(biāo)簽的enctype屬性規(guī)定了表單信息在發(fā)送到服務(wù)器之前,應(yīng)該如何對(duì)數(shù)據(jù)進(jìn)行編碼。而且編碼的格式由它的三個(gè)屬性值決定:

application/x-www-form-urlencoded //在發(fā)送前編碼所有字符(默認(rèn))multipart/form-data //不對(duì)字符編碼。在使用包含文件上傳控件的表單時(shí),必須使用該值。text/plain //空格轉(zhuǎn)換為 "+" 加號(hào),但不對(duì)特殊字符編碼。

在普通的HTTP POST請(qǐng)求中,Content-Type 為 application/x-www-form-urlencoded,參數(shù)是在請(qǐng)求體中。即在請(qǐng)求的Form Data中。

而如果使用原生的AJAX POST請(qǐng)求,請(qǐng)求的 Content-Type 為 text/plain;charset=UTF-8 ,并且請(qǐng)求的參數(shù)在Request Payload中。

因此:在使用原生的AJAX POST請(qǐng)求時(shí),要明確設(shè)置請(qǐng)求頭的Content-Type屬性值。(其實(shí)我很想知道如果我就放在Request Payload中,服務(wù)器是拿不到數(shù)據(jù)嗎?)

在我開發(fā)過程中響應(yīng)頭headers中的Content-Type較為常用的有三個(gè)值(其實(shí)常用的不只有這三個(gè)):

1.application/x-www-form-urlencoded:這個(gè)值是form表單的默認(rèn)屬性的屬性值,而且JQuery的AJAX的Content-Type默認(rèn)值也是這個(gè)。

2.multipart/form-data:在使用表單上傳文件的時(shí)候,enctype一定要用到這個(gè)屬性值。詳細(xì)的請(qǐng)問度娘。

3.application/ json:這個(gè)值我經(jīng)常用到,因?yàn)槲覀兊暮笈_(tái)工程師需要我傳JSON給他。這個(gè)屬性值告訴服務(wù)器,此次請(qǐng)求的消息主體是JSON的格式。此前在AngularJs項(xiàng)目中也有見過,它的AJAX請(qǐng)求默認(rèn)的就是JSON字符串。并且JSON 格式支持比鍵值對(duì)復(fù)雜得多的結(jié)構(gòu)化數(shù)據(jù)(那種層級(jí)很深的想想都蛋疼)。

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動(dòng)畫培訓(xùn)

 

   本文原文出自MINGXINICE的博客:http://www.cnblogs.com/mingxinice/p/vue-ajax-cors.html

正題:Vue中應(yīng)用CORS實(shí)現(xiàn)AJAX跨域

ok終于把基礎(chǔ)知識(shí)梳理完了,下面我就要開始說Vue中對(duì)CORS的應(yīng)用,以及它如何設(shè)置它的參數(shù)放在哪里了。

在Vue中想實(shí)現(xiàn)與后臺(tái)的數(shù)據(jù)交互,缺少不了vue-resource模塊。就像jQuery里的$.ajax,用來和后端交互數(shù)據(jù)的。

正是vue-resource應(yīng)用到了W3C中的新特性CORS。目前大部分的瀏覽器都已經(jīng)支持 XMLHttpRequest2 對(duì)象用于在后臺(tái)與服務(wù)器交換數(shù)據(jù)。

但是在Vue中提交AJAX跨域請(qǐng)求時(shí),我們?nèi)诵枰喇?dāng)前瀏覽器是否支持 XMLHttpRequest2。判斷的方法是使用in操作檢測(cè)當(dāng)前XMLHttpRequest示例對(duì)象是否包含withCredentials屬性,如果包含則支持CORS(因?yàn)閣ithCredentials屬性是XMLHttpRequest對(duì)象獨(dú)有的,且如上文說,它是跨域傳輸Cookie和HTTP認(rèn)證信息的關(guān)鍵)。

var xhrCors = 'withCredentials' in new XMLHttpRequest()

在支持CORS的情況下,還需要服務(wù)器啟用CORS支持。

如果我們想從http://example.com域中提交請(qǐng)求到http://crossdimain.com域,那么需要在crossdomain.com域中添加如下請(qǐng)求頭:

Access-Control-Allow-Origin : http://example.com

如果crossdomian.com要允許所有異域都可以AJAX請(qǐng)求該域資源,則添加如下響應(yīng)頭:

Access-Control-Allow-Origin : *

這樣服務(wù)器開啟CORS支持后,在瀏覽器中就可以像提交普通的AJAX請(qǐng)求一樣,提交跨域請(qǐng)求了。

而真正知道這些后,在應(yīng)用到開發(fā)環(huán)境中還會(huì)發(fā)現(xiàn)一個(gè)小坑:這個(gè)$http請(qǐng)求并不像jquery的ajax一樣,這里的post的data默認(rèn)不是以form data的形式,而是request payload。(根據(jù)上述研究,可以判斷Vue的AJAX請(qǐng)求,很可能是以原生的方式,這里小生純屬猜測(cè))

在學(xué)習(xí)了上述的基礎(chǔ)知識(shí)后,才發(fā)現(xiàn)這個(gè)小坑很好解決。我們只需要把請(qǐng)求頭的 Content-Type 值設(shè)置為 application/x-www-form-urlencoded 即可。我的項(xiàng)目代碼如下:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動(dòng)畫培訓(xùn)

this.$http.post(                
  'https://zmx.mxorz.com/user/userCenter', {
     usertId: usertId
   }, {       'headers': {           'Content-Type': 'application/x-www-form-urlencoded'
       }
   }
).then(function(res) {                
}, function(res) {
})

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動(dòng)畫培訓(xùn)

但是還有一種方法,是直接設(shè)置 emulateJSON 屬性為 true。感覺這個(gè)放方法的易用性更強(qiáng)。我的項(xiàng)目代碼如下:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動(dòng)畫培訓(xùn)

this.$http.post(                
  'https://zmx.mxorz.com/user/userCenter', {
     usertId: usertId
   }, {
      emulateJSON:true
   }, {       'headers': {           'Content-Type': 'application/json'
       }
   }
).then(function(res) {                
}, function(res) {
})

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動(dòng)畫培訓(xùn)

  具體的梳理只有這么多,對(duì)Vue的各方面理解并不是很細(xì)致,望各位大佬多多提點(diǎn)~

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動(dòng)畫培訓(xùn)

 

 

標(biāo)簽: VueCORS跨域資源共享AJAXform datawithCredentialsrequest payload

http://www.cnblogs.com/mingxinice/p/vue-ajax-cors.html