6.跨域資源共享CORS

Cross-Origin Resource Sharing?(CORS) is a mechanism that uses additional?HTTP?headers to tell browsers to give a web application running at one?origin, access to selected resources from a different origin.

它允許瀏覽器向跨源服務(wù)器發(fā)出XMLHttpRequest芜壁,從而克服了AJAX只能同源使用的限制袜蚕。CORS也已成為主流的跨域解決方案。


瀏覽器將CORS跨域請(qǐng)求分為簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求宽档,瀏覽器對(duì)這兩種的處理是不一樣的。

只要同時(shí)滿足兩個(gè)條件惜傲,就屬于簡(jiǎn)單請(qǐng)求:

(1)使用下列方法之一:

head/get/post

(2)請(qǐng)求的Heder是

Accept

Accept-Language

Content-Language

3)Content-Type只限于三個(gè)值:

application/x-www-form-urlencoded

multipart/form-data

text/plain


對(duì)于簡(jiǎn)單請(qǐng)求瀏覽器直接發(fā)出CORS請(qǐng)求,具體就是在頭信息之中增加一個(gè)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字段用來(lái)說(shuō)明本次請(qǐng)求來(lái)自哪個(gè)源(協(xié)議 + 域名 + 端口),服務(wù)器根據(jù)這個(gè)值決定是否同意這次請(qǐng)求屑那。


CORS請(qǐng)求設(shè)置的響應(yīng)頭字段拱镐,都以 Access-Control-開(kāi)頭:

1)Access-Control-Allow-Origin:必選

它的值要么是請(qǐng)求時(shí)Origin字段的值,要么是一個(gè)*持际,表示接受任意域名的請(qǐng)求沃琅。

2)Access-Control-Allow-Credentials:可選

它的值是一個(gè)布爾值,表示是否允許發(fā)送Cookie蜘欲。默認(rèn)情況下Cookie不包括在CORS請(qǐng)求之中益眉,設(shè)為true即表示服務(wù)器明確許可,Cookie可以包含在請(qǐng)求中一起發(fā)給服務(wù)器。這個(gè)值也只能設(shè)為true郭脂,如果服務(wù)器不要瀏覽器發(fā)送Cookie年碘,刪除該字段即可。

需注意的是:由于同源策略的限制展鸡,所讀取的cookie為跨域請(qǐng)求接口所在域的cookie屿衅,而非當(dāng)前頁(yè)。

3)Access-Control-Expose-Headers:可選

CORS請(qǐng)求時(shí)娱颊,XMLHttpRequest對(duì)象的getResponseHeader()方法只能拿到6個(gè)基本字段:Cache-Control傲诵、Content-Language、Content-Type箱硕、Expires拴竹、Last-Modified、Pragma剧罩。如果想拿到其他字段栓拜,就必須在Access-Control-Expose-Headers里面指定。上面例子指定惠昔,getResponseHeader('FooBar')可以返回FooBar字段的值幕与。


非簡(jiǎn)單請(qǐng)求是那種對(duì)服務(wù)器有特殊要求的請(qǐng)求,比如請(qǐng)求方法是PUT或DELETE镇防,或者Content-Type字段的類型是application/json啦鸣。非簡(jiǎn)單請(qǐng)求的CORS請(qǐng)求,會(huì)在正式通信之前来氧,增加一次HTTP查詢請(qǐng)求诫给,稱為"預(yù)檢"請(qǐng)求(preflight)。

預(yù)檢請(qǐng)求用的請(qǐng)求方法是OPTIONS啦扬,表示這個(gè)請(qǐng)求是用來(lái)詢問(wèn)的中狂。請(qǐng)求頭信息里面,關(guān)鍵字段是Origin扑毡,表示請(qǐng)求來(lái)自哪個(gè)源胃榕。除了Origin字段,預(yù)檢請(qǐng)求的頭信息包括兩個(gè)特殊字段瞄摊。

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..

1)Access-Control-Request-Method:必選

用來(lái)列出瀏覽器的CORS請(qǐng)求會(huì)用到哪些HTTP方法勋又,上例是PUT。

2)Access-Control-Request-Headers:可選

該字段是一個(gè)逗號(hào)分隔的字符串换帜,指定瀏覽器CORS請(qǐng)求會(huì)額外發(fā)送的頭信息字段楔壤,上例是X-Custom-Header。


服務(wù)器收到預(yù)檢請(qǐng)求膜赃,檢查了Origin挺邀、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,確認(rèn)允許跨源請(qǐng)求,就可以做出回應(yīng)端铛。

HTTP回應(yīng)中泣矛,除了關(guān)鍵的是Access-Control-Allow-Origin字段,其他CORS相關(guān)字段如下:

1)Access-Control-Allow-Methods:必選

它的值是逗號(hào)分隔的一個(gè)字符串禾蚕,表明服務(wù)器支持的所有跨域請(qǐng)求的方法您朽。注意,返回的是所有支持的方法换淆,而不單是瀏覽器請(qǐng)求的那個(gè)方法哗总,這是為了避免多次預(yù)檢請(qǐng)求。

2)Access-Control-Allow-Headers

如果瀏覽器請(qǐng)求包括Access-Control-Request-Headers字段倍试,則Access-Control-Allow-Headers字段是必需的讯屈。它也是一個(gè)逗號(hào)分隔的字符串,表明服務(wù)器支持的所有頭信息字段县习,不限于瀏覽器在預(yù)檢中請(qǐng)求的字段涮母。

3)Access-Control-Allow-Credentials:可選

該字段與簡(jiǎn)單請(qǐng)求時(shí)的含義相同。

4)Access-Control-Max-Age:可選

用來(lái)指定本次預(yù)檢請(qǐng)求的有效期躁愿,單位為秒叛本。


普通跨域請(qǐng)求只服務(wù)端設(shè)置Access-Control-Allow-Origin即可,前端無(wú)須設(shè)置彤钟。若要帶cookie請(qǐng)求来候,前后端都需要設(shè)置。

1逸雹、 前端設(shè)置:

1.)原生ajax

// 前端設(shè)置是否帶cookie

xhr.withCredentials =true;


示例代碼:

var xhr = new XMLHttpRequest();?

// 前端設(shè)置是否帶cookie

xhr.withCredentials =true;

xhr.open('post', 'http://www.domain2.com:8080/login', true);

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

xhr.send('user=admin');

xhr.onreadystatechange = function() {

? ? if (xhr.readyState == 4 && xhr.status == 200) {

? ? ? ? alert(xhr.responseText);

? ? }

};


2.)jQuery ajax

$.ajax({

? ? ...

? ?xhrFields: {

? ? ? ?withCredentials: true? ? // 前端設(shè)置是否帶cookie

? ?},

? ?crossDomain: true,? // 會(huì)讓請(qǐng)求頭中包含跨域的額外信息营搅,但不會(huì)含cookie

? ? ...

});


3.)vue框架

a.) axios設(shè)置:

axios.defaults.withCredentials =?true

b.) vue-resource設(shè)置:

Vue.http.options.credentials =?true


2、 服務(wù)端設(shè)置:

若后端設(shè)置成功峡眶,前端瀏覽器控制臺(tái)則不會(huì)出現(xiàn)跨域報(bào)錯(cuò)信息剧防,反之植锉,說(shuō)明沒(méi)設(shè)成功辫樱。

1.)Java后臺(tái):

/*

* 導(dǎo)入包:import javax.servlet.http.HttpServletResponse;

* 接口參數(shù)中定義:HttpServletResponse response

*/

// 允許跨域訪問(wèn)的域名:若有端口需寫全(協(xié)議+域名+端口),若沒(méi)有端口末尾不用加'/'

response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com");

// 允許前端帶認(rèn)證cookie:?jiǎn)⒂么隧?xiàng)后俊庇,上面的域名不能為'*'狮暑,必須指定具體的域名,否則瀏覽器會(huì)提示

response.setHeader("Access-Control-Allow-Credentials", "true");

// 提示OPTIONS預(yù)檢時(shí)辉饱,后端需要設(shè)置的兩個(gè)常用自定義頭

response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");

2.)Nodejs后臺(tái)示例:

var http = require('http');

var server = http.createServer();

var qs = require('querystring');

server.on('request', function(req, res) {

? ? var postData = '';

? ? // 數(shù)據(jù)塊接收中

? ? req.addListener('data', function(chunk) {

? ? ? ? postData += chunk;

? ? });

? ? // 數(shù)據(jù)接收完畢

? ? req.addListener('end', function() {

? ? ? ? postData = qs.parse(postData);

? ? ? ? // 跨域后臺(tái)設(shè)置

? ? ? ? res.writeHead(200, {

? ? ? ? ? ? 'Access-Control-Allow-Credentials': 'true',? ? // 后端允許發(fā)送Cookie

? ? ? ? ? ? 'Access-Control-Allow-Origin': 'http://www.domain1.com',? ? // 允許訪問(wèn)的域(協(xié)議+域名+端口)

? ? ? ? ? ? /*

? ? ? ? ? ? * 此處設(shè)置的cookie還是domain2的而非domain1搬男,因?yàn)楹蠖艘膊荒芸缬驅(qū)慶ookie(nginx反向代理可以實(shí)現(xiàn)),

? ? ? ? ? ? * 但只要domain2中寫入一次cookie認(rèn)證彭沼,后面的跨域接口都能從domain2中獲取cookie缔逛,從而實(shí)現(xiàn)所有的接口都能跨域訪問(wèn)

? ? ? ? ? ? */

? ? ? ? ? ? 'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'? // HttpOnly的作用是讓js無(wú)法讀取cookie

? ? ? ? });

? ? ? ? res.write(JSON.stringify(postData));

? ? ? ? res.end();

? ? });

});

server.listen('8080');

console.log('Server is running at port 8080...');


cors要允許*.qq.com訪問(wèn)怎么設(shè)置?有一個(gè)a.qq.com的圖片發(fā)到百度貼吧上,會(huì)不會(huì)帶上那個(gè)cookie褐奴?

能說(shuō)說(shuō)同源策略嗎按脚,那如果是直接請(qǐng)求ip會(huì)有同源策略嗎,如果一個(gè)域名對(duì)應(yīng)多個(gè)ip的情況呢敦冬?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辅搬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子脖旱,更是在濱河造成了極大的恐慌堪遂,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萌庆,死亡現(xiàn)場(chǎng)離奇詭異溶褪,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)践险,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門竿滨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人捏境,你說(shuō)我怎么就攤上這事于游。” “怎么了垫言?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵贰剥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我筷频,道長(zhǎng)蚌成,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任凛捏,我火速辦了婚禮担忧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坯癣。我一直安慰自己瓶盛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布示罗。 她就那樣靜靜地躺著惩猫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚜点。 梳的紋絲不亂的頭發(fā)上轧房,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音绍绘,去河邊找鬼奶镶。 笑死迟赃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的厂镇。 我是一名探鬼主播捺氢,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼剪撬!你這毒婦竟也來(lái)了摄乒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤残黑,失蹤者是張志新(化名)和其女友劉穎馍佑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體梨水,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拭荤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疫诽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舅世。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖奇徒,靈堂內(nèi)的尸體忽然破棺而出雏亚,到底是詐尸還是另有隱情,我是刑警寧澤摩钙,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布罢低,位于F島的核電站,受9級(jí)特大地震影響胖笛,放射性物質(zhì)發(fā)生泄漏网持。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一长踊、第九天 我趴在偏房一處隱蔽的房頂上張望功舀。 院中可真熱鬧,春花似錦身弊、人聲如沸辟汰。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)莉擒。三九已至酿炸,卻和暖如春瘫絮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背填硕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工麦萤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹿鳖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓壮莹,卻偏偏與公主長(zhǎng)得像翅帜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子命满,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 歡迎關(guān)注微信公眾號(hào):全棧工廠 本文主要參考跨域資源共享 CORS 詳解[http://www.ruanyifeng...
    liqingbiubiu閱讀 1,828評(píng)論 0 3
  • 什么是跨域 跨域涝滴,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的胶台,是瀏覽器對(duì)JavaScript實(shí)...
    HeroXin閱讀 833評(píng)論 0 4
  • CORS是一個(gè)W3C標(biāo)準(zhǔn)歼疮,全稱是"跨域資源共享"(Cross-origin resource sharing)。 ...
    奇特思維家閱讀 1,119評(píng)論 0 3
  • 什么是跨域 跨域诈唬,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本韩脏。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript實(shí)...
    Yaoxue9閱讀 1,288評(píng)論 0 6
  • 認(rèn)真練習(xí)幾多天铸磅, 輕歌曼舞一瞬間赡矢。 若想他日成功名, 刻苦努力勇往前阅仔!
    西北山閱讀 254評(píng)論 0 2