弄懂CORS

OK but no!

原文鏈接:https://medium.com/@baphemot/understanding-cors-18ad6b478e2b


如果你在前端使用過(guò)AJAX,你應(yīng)該對(duì)下面出現(xiàn)在瀏覽器控制臺(tái)里的錯(cuò)誤很熟悉帖汞。如果你沒(méi)見(jiàn)過(guò)脖咐,那只能說(shuō)明你還年輕竹挡。


Failed to load?https://example.com/: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘https://anfo.pl'?is therefore not allowed access. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.


如果你看到這個(gè)錯(cuò)誤信息,這表示這次返回?cái)?shù)據(jù)失敗了臊泰,但是你仍然可以打開(kāi)瀏覽器的Network欄缔御,看到返回的數(shù)據(jù)——這到底是怎么回事惜颇?

Cross-Origin Resource Sharing?(CORS)

上面的錯(cuò)誤是因?yàn)闉g覽器的CORS機(jī)制導(dǎo)致的皆刺。COSR(跨站點(diǎn)資源分享)通俗的講是跨域問(wèn)題,嚴(yán)格來(lái)說(shuō)它是跨域問(wèn)題的解決方案之一凌摄,而且是官方解決方案羡蛾。


在CORS成為標(biāo)準(zhǔn)之前,是沒(méi)有辦法請(qǐng)求不同域名的后端API的锨亏,因?yàn)榘踩虺赵埂U?qǐng)求會(huì)被同源策略阻止,現(xiàn)在也是器予。


CORS是一種可以讓你實(shí)現(xiàn)跨站點(diǎn)請(qǐng)求并同時(shí)阻止惡意js的請(qǐng)求浪藻,它會(huì)在你發(fā)送下面幾種HTTP請(qǐng)求時(shí)觸發(fā):

- 不同的域名 (比如在網(wǎng)站 example.com 請(qǐng)求 api.com)

- 不同的子域名 (比如在網(wǎng)站 example.com 請(qǐng)求 api.example.com)

- 不同的端口 (比如在網(wǎng)站 example.com 請(qǐng)求 example.com:3001)

- 不同協(xié)議 (比如在網(wǎng)站 https://example.com 請(qǐng)求 http://example.com)

這個(gè)機(jī)制阻止攻擊者在一些網(wǎng)站上放置js腳本(比如通過(guò)Googls Ads展示的廣告)發(fā)起一個(gè)AJAX請(qǐng)求訪問(wèn)www.yourbank.com,假設(shè)你剛好登陸過(guò)這個(gè)網(wǎng)站乾翔,就可能使用你的驗(yàn)證信息發(fā)起一筆轉(zhuǎn)賬爱葵。

如果你的瀏覽器發(fā)起一個(gè)“非簡(jiǎn)單”請(qǐng)求(比如這個(gè)請(qǐng)求里包含了cookies,或者Content-type不包含application/x-ww-form-urlencoded,?multipart/form-data 或者 text-plain)一個(gè)叫做預(yù)檢查的機(jī)制會(huì)發(fā)送一個(gè)OPTIONS請(qǐng)求到服務(wù)器反浓。如果服務(wù)器沒(méi)有返回帶有特殊頭部的數(shù)據(jù)萌丈,簡(jiǎn)單請(qǐng)求GET或者POST請(qǐng)求仍然會(huì)發(fā)送,服務(wù)器的數(shù)據(jù)也會(huì)返回雷则,但是瀏覽器會(huì)阻止Javascript獲取這次請(qǐng)求辆雾。

如果明確的需要在一個(gè)請(qǐng)求里添加cookies,自定義頭部信息或則其他特性月劈,這將不在是一個(gè)簡(jiǎn)單請(qǐng)求度迂,并且服務(wù)器沒(méi)有適當(dāng)?shù)姆祷靥僖遥@次請(qǐng)求講不會(huì)發(fā)送。就是復(fù)雜請(qǐng)求時(shí)惭墓,如果OPTIONS的請(qǐng)求湾盒,服務(wù)器沒(méi)有做出適當(dāng)?shù)姆祷兀竺嬲鎸?shí)的請(qǐng)求將不會(huì)發(fā)送诅妹。

Access-Control-Allow-What?

CORS使用一些HTTP頭信息——包括請(qǐng)求和返回——為了讓工作繼續(xù)開(kāi)展下去罚勾,你必須了解一下的一些頭信息:

Access-Control-Allow-Origin

這個(gè)頭部信息由服務(wù)器返回,用來(lái)明確指定那些客戶(hù)端的域名允許訪問(wèn)這個(gè)資源吭狡。它的值可以是:

- * —— 允許任意域名

- 一個(gè)完整的域名名字(比如:https://example.com)

如果你需要客戶(hù)端傳遞驗(yàn)證信息到頭部(比如:cookies)尖殃。這個(gè)值不能為 * —— 必須為完整的域名(這點(diǎn)很重要)。

Access-Control-Allow-Credentials

這個(gè)頭部信息只會(huì)在服務(wù)器支持通過(guò)cookies傳遞驗(yàn)證信息的返回?cái)?shù)據(jù)里划煮。它的值只有一個(gè)就是 true送丰。跨站點(diǎn)帶驗(yàn)證信息時(shí)弛秋,服務(wù)器必須要爭(zhēng)取設(shè)置這個(gè)值器躏,服務(wù)器才能獲取到用戶(hù)的cookie。

Access-Control-Allow-Headers

提供一個(gè)逗號(hào)分隔的列表表示服務(wù)器支持的請(qǐng)求數(shù)據(jù)類(lèi)型蟹略。假如你使用自定義頭部(比如:x-authentication-token 服務(wù)器需要在返回OPTIONS請(qǐng)求時(shí)登失,要把這個(gè)值放到這個(gè)頭部里,否則請(qǐng)求會(huì)被阻止)挖炬。

Access-Control-Expose-Headers

相似的揽浙,這個(gè)返回信息里包含了一組頭部信息,這些信息表示那些客戶(hù)端可以使用意敛。其他沒(méi)有在里面的頭部信息將會(huì)被限制(譯者注:這個(gè)頭信息實(shí)戰(zhàn)中使用較少)馅巷。

Access-Control-Allow-Methods

一個(gè)逗號(hào)分隔的列表,表明服務(wù)器支持的請(qǐng)求類(lèi)型(比如:GET, POST)

Origin

這個(gè)頭部信息草姻,屬于請(qǐng)求數(shù)據(jù)的一部分钓猬。這個(gè)值表明這個(gè)請(qǐng)求是從瀏覽器打開(kāi)的哪個(gè)域名下發(fā)出的。出于安全原因撩独,瀏覽器不允許你修改這個(gè)值敞曹。

如何修復(fù)CORS“錯(cuò)誤”?

你應(yīng)該明白了CORS的行為并不是一個(gè)錯(cuò)誤——它是一個(gè)機(jī)制跌榔,用來(lái)保護(hù)你的用戶(hù)异雁,你和你請(qǐng)求的服務(wù)器。

有時(shí)僧须,缺乏適當(dāng)?shù)念^部信息是因?yàn)榭蛻?hù)端實(shí)現(xiàn)錯(cuò)誤(比如:丟失驗(yàn)證信息比如API key)纲刀。

下面有幾個(gè)適應(yīng)不同情況,“修復(fù)這個(gè)錯(cuò)誤”的方法:

A——我在開(kāi)發(fā)前端并且可以控制或者認(rèn)識(shí)開(kāi)發(fā)后端的人員

這是一個(gè)最好的情況——你應(yīng)該能讓返回信息的頭里包含適當(dāng)?shù)腃ORS字段。如果你請(qǐng)求的API使用node的experss示绊,你可以使用cors包锭部。如果你想讓你的網(wǎng)站更加的安全,你應(yīng)該使用白名單來(lái)返回Access-Control-Allow-Origin頭面褐。

B——我在開(kāi)發(fā)前端拌禾,但是我不能控制后端,我需要一個(gè)臨時(shí)方案

這是第二個(gè)最好的情況展哭,特別是在有時(shí)間限制的情況里湃窍。臨時(shí)的解決這個(gè)問(wèn)題可以讓你的瀏覽器忽略CORS機(jī)制——比如安裝ACAOChrmoe插件或者啟動(dòng)Chrome時(shí)輸入下面的指令:

chrome --disable-web-security --user-data-dir

重要:需要記住的是,這個(gè)方法會(huì)關(guān)閉整個(gè)瀏覽器的CORS機(jī)制匪傍,包含你瀏覽器正在訪問(wèn)的網(wǎng)站您市,要小心使用,非常不安全役衡。(譯者注:這個(gè)方法沒(méi)有用過(guò)茵休,個(gè)人覺(jué)得風(fēng)險(xiǎn)太大,臨時(shí)測(cè)試也慎用手蝎,怕你開(kāi)了插件忘記關(guān)掉)

其他方法可以使用devServer.proxy(假設(shè)你使用webpack來(lái)啟動(dòng)你的app)或者使用CORS-as-a-service解決方案榕莺,比如https://cors-anywhere.herokuapp.com/

C——我在開(kāi)發(fā)前端,但是我控制不了后端棵介,而且將來(lái)也控制不了

好的钉鸯。事情越來(lái)越復(fù)雜了。首先鞍时,你應(yīng)該思考亏拉,為什么服務(wù)器沒(méi)有返回適當(dāng)?shù)念^部扣蜻。

也許你請(qǐng)求的API不許允第三方應(yīng)用請(qǐng)求它們逆巍?或者這些API僅僅給APP使用,而不是瀏覽器莽使?或者你應(yīng)該發(fā)送一個(gè)驗(yàn)證token在你請(qǐng)求的URL里锐极?

假如你堅(jiān)持要通過(guò)瀏覽器獲得它們的數(shù)據(jù),你應(yīng)該自己寫(xiě)一個(gè)代理芳肌,在瀏覽器和你要請(qǐng)求的API之間灵再。就像我們?cè)诜椒˙里做的那樣。


在中間加一個(gè)代理

這個(gè)代理沒(méi)有運(yùn)行在和你應(yīng)用相同的域名下亿笤,但是這個(gè)代理為你的請(qǐng)求提供正確的CORS響應(yīng)翎迁。這個(gè)代理去請(qǐng)求API時(shí)就不需要CORS支持,因?yàn)檫@個(gè)代理不是用瀏覽器去訪問(wèn)的API净薛,而是通過(guò)程序直接發(fā)起的請(qǐng)求汪榔。

你可以根據(jù)你的平臺(tái)實(shí)現(xiàn)這個(gè)代理,或者使用已經(jīng)做好的解決方案肃拜,比如:https://www.npmjs.com/package/cors-anywhere

請(qǐng)記住痴腌,如果你想支持用戶(hù)驗(yàn)證雌团,這些方法會(huì)引入安全風(fēng)險(xiǎn)。

譯者注:實(shí)戰(zhàn)中士聪,能控制服務(wù)器的情況下锦援。最好是服務(wù)器上正確配置CORS,可以在服務(wù)器API層進(jìn)行配置剥悟,也可以在nginx或者apache層進(jìn)行配置(這樣后端新加服務(wù)器不用再配置)灵寺。最好配置上白名單。真實(shí)項(xiàng)目中区岗,CORS問(wèn)題主要出現(xiàn)在開(kāi)發(fā)階段替久,本地啟動(dòng)的前端開(kāi)發(fā)服務(wù)器域名是localhost。調(diào)試接口可能是一個(gè)其他域名躏尉,這個(gè)時(shí)候的解決方法蚯根。AC都可以,不過(guò)C方法會(huì)導(dǎo)致每個(gè)前端項(xiàng)目都需要自己的開(kāi)發(fā)服務(wù)器支持一個(gè)proxy胀糜。個(gè)人偏向去測(cè)試環(huán)境的nginx服務(wù)層配置跨域颅拦,這樣,開(kāi)發(fā)環(huán)境統(tǒng)一支持前端本地開(kāi)發(fā)跨域調(diào)試接口教藻。

更多關(guān)于CORS

如果你希望學(xué)習(xí)更多關(guān)于CORS的細(xì)節(jié)距帅,請(qǐng)?jiān)L問(wèn)MDN article

推薦一個(gè)模擬接口的應(yīng)用括堤,可以在你本地開(kāi)發(fā)前端碌秸,但是后端你不能直接訪問(wèn)或者還沒(méi)寫(xiě)好時(shí),模擬調(diào)試你的接口https://www.npmjs.com/package/back-mock

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末悄窃,一起剝皮案震驚了整個(gè)濱河市讥电,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌轧抗,老刑警劉巖恩敌,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異横媚,居然都是意外死亡纠炮,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)灯蝴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)恢口,“玉大人,你說(shuō)我怎么就攤上這事穷躁「纾” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)看疗。 經(jīng)常有香客問(wèn)我沙峻,道長(zhǎng),這世上最難降的妖魔是什么两芳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任摔寨,我火速辦了婚禮,結(jié)果婚禮上怖辆,老公的妹妹穿的比我還像新娘是复。我一直安慰自己,他們只是感情好竖螃,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布淑廊。 她就那樣靜靜地躺著,像睡著了一般特咆。 火紅的嫁衣襯著肌膚如雪季惩。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天腻格,我揣著相機(jī)與錄音画拾,去河邊找鬼。 笑死菜职,一個(gè)胖子當(dāng)著我的面吹牛青抛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播酬核,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蜜另,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了嫡意?” 一聲冷哼從身側(cè)響起举瑰,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鹅很,沒(méi)想到半個(gè)月后嘶居,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡促煮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了整袁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片菠齿。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖坐昙,靈堂內(nèi)的尸體忽然破棺而出绳匀,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布疾棵,位于F島的核電站戈钢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏是尔。R本人自食惡果不足惜殉了,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拟枚。 院中可真熱鬧薪铜,春花似錦、人聲如沸恩溅。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)脚乡。三九已至蜒滩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奶稠,已是汗流浹背帮掉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窒典,地道東北人蟆炊。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瀑志,于是被迫代替她去往敵國(guó)和親涩搓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理劈猪,服務(wù)發(fā)現(xiàn)昧甘,斷路器,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • 歡迎關(guān)注微信公眾號(hào):全棧工廠 本文主要參考跨域資源共享 CORS 詳解[http://www.ruanyifeng...
    liqingbiubiu閱讀 1,828評(píng)論 0 3
  • API定義規(guī)范 本規(guī)范設(shè)計(jì)基于如下使用場(chǎng)景: 請(qǐng)求頻率不是非常高:如果產(chǎn)品的使用周期內(nèi)請(qǐng)求頻率非常高战得,建議使用雙通...
    有涯逐無(wú)涯閱讀 2,521評(píng)論 0 6
  • 題目1.什么是同源策略? 同源策略(Same origin Policy): 瀏覽器出于安全方面的考慮充边,只允許與本...
    FLYSASA閱讀 1,709評(píng)論 0 6
  • 最近公司出了一項(xiàng)新的政策,每天上班之前必須要有人演講5-10分鐘常侦,題材不限浇冰,每天用手機(jī)錄下來(lái)發(fā)給總部! ...
    2b0221959192閱讀 307評(píng)論 1 0