CORS(Cross-origin resource sharing)是一種安全機(jī)制,允許其他域請(qǐng)求獲取到當(dāng)前域中web頁面中的限制資源。web頁面可以自由的嵌入圖片,樣式,腳本,iframe,視頻等資源,但是由于同源策略的限制,跨域請(qǐng)求會(huì)被限制。
CORS定義了一種方式,通過這種方式瀏覽器和服務(wù)器可以互相確定允許跨域請(qǐng)求是否是安全的。這樣就比單純的同源請(qǐng)求有更多的自由度,也可以實(shí)現(xiàn)更多的功能,而且也比允許全部的跨域請(qǐng)求更安全。CORS是W3C中的一個(gè)推薦標(biāo)準(zhǔn)。
CORS原理
CORS標(biāo)準(zhǔn)介紹了新的HTTP headers,在瀏覽器和服務(wù)器都獲得授權(quán)的情況下,這些headers給它們提供了一種訪問遠(yuǎn)程URL的方式。盡管服務(wù)器可以執(zhí)行一些驗(yàn)證和授權(quán),但是瀏覽器也有責(zé)任來支持這些headers,遵循限制。
對(duì)于AJAX和可以修改數(shù)據(jù)的HTTP請(qǐng)求方法來說,規(guī)范規(guī)定瀏覽器預(yù)檢查請(qǐng)求,通過請(qǐng)求頭中的OPTIONS方法獲取服務(wù)端支持的請(qǐng)求方法,然后得到服務(wù)器的批準(zhǔn)之后,使用真實(shí)的HTTP請(qǐng)求方法發(fā)送真實(shí)的請(qǐng)求。服務(wù)器也可以通知客戶端是否需要隨請(qǐng)求發(fā)送證書(包括Cookies和HTTP認(rèn)證數(shù)據(jù))。
簡(jiǎn)單示例
當(dāng)支持CORS的瀏覽器嘗試發(fā)起跨域請(qǐng)求時(shí):
1.瀏覽器發(fā)送OPTIONS請(qǐng)求,并在HTTP頭中指定Origin,Origin的值是提供父級(jí)頁面的域。當(dāng)前域http://www.foo.com中的頁面嘗試獲取域http://www.bar.com中的用戶數(shù)據(jù)時(shí),下面的請(qǐng)求頭將會(huì)發(fā)送給http://www.bar.com域:
Origin:http://www.foo.com
2.服務(wù)器可能會(huì)有下面的響應(yīng):
- 響應(yīng)頭中的Access-Control-Allow-Origin標(biāo)識(shí)允許那個(gè)來源站點(diǎn)。例如:
Access-Control-Allow-Origin: http://www.foo.com - 如果服務(wù)器不支持跨域請(qǐng)求會(huì)返回錯(cuò)誤頁面
- 響應(yīng)頭中的Access-Control-Allow-Origin如果是通配符則表示允許任何域訪問:
Access-Control-Allow-Origin: *
當(dāng)一個(gè)頁面或者API是完全公開的,并且可以被任何人或者任意站點(diǎn)上的代碼訪問時(shí),通配符同源策略是一個(gè)好的方法。例如在公共托管服務(wù)上的免費(fèi)可用的Google字體。
通配符*意味著服務(wù)器不需要請(qǐng)求提供憑證,有意義的HTTP身份驗(yàn)證,客戶端的SSL驗(yàn)證,也不允許發(fā)送cookies。
注意在CORS架構(gòu)中,Access-Control-Allow-Origin頭是外部web服務(wù)器(http://www.bar.com)設(shè)置的,而不是源web服務(wù)器(http://www.foo.com)設(shè)置的。CORS允許外部web服務(wù)器授權(quán)web應(yīng)用使用它的服務(wù),不控制web應(yīng)用訪問外部服務(wù)。
預(yù)檢查示例
執(zhí)行某些類型的跨域ajax請(qǐng)求時(shí),支持CORS的瀏覽器會(huì)插入一個(gè)額外的預(yù)檢查請(qǐng)求來決定是否有權(quán)限執(zhí)行相應(yīng)的動(dòng)作。
OPTIONS /
Host: bar.com
Origin: http://foo.com
如果bar.com想要接收這種行為,它可能會(huì)回復(fù)下面的響應(yīng)頭:
Access-Control-Allow-Origin: http://foo.com
Access-Control-Allow-Methods: PUT, DELETE
Headers
CORS相關(guān)的HTTP頭如下:
請(qǐng)求頭
- Origin
- Access-Control-Request-Method
- Access-Control-Request-Headers
響應(yīng)頭
- Access-Control-Allow-Origin
- Access-Control-Allow-Credentials
- Access-Control-Expose-Headers
- Access-Control-Max-Age
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
瀏覽器支持情況
瀏覽器支持詳情可以參考can I use網(wǎng)站上面的統(tǒng)計(jì),點(diǎn)這里查看詳情。
歷史
跨域支持最早是在2004年的VoiceXML中作為一個(gè)雜項(xiàng)提出的,主要是為了支持VoiceXML瀏覽器可以安全獲取跨域數(shù)據(jù)。機(jī)制本質(zhì)上是通用的,在VoiceXML中沒有具體化,隨后被分配到一個(gè)實(shí)現(xiàn)備忘中。然后主要瀏覽器廠商參與的W3C的WebApps工作組開始把備忘錄規(guī)范化成W3C工作草案,最后才慢慢變成W3C推薦標(biāo)準(zhǔn)。
CORS和JSONP對(duì)比
CORS可以作為JSONP模式的一個(gè)現(xiàn)代選擇。JSONP只支持GET請(qǐng)求,而CORS也支持其他類型的HTTP請(qǐng)求方法。使用CORS,開發(fā)者可以正常使用XMLHttpRequest對(duì)象發(fā)送請(qǐng)求,這種方法處理錯(cuò)誤比JSONP方便。從另一方面來說,JSONP可以兼容不支持CORS的老版瀏覽器。CORS只能被大多數(shù)現(xiàn)代瀏覽器支持。JSONP可能導(dǎo)致XSS問題,而CORS允許站點(diǎn)手動(dòng)解析響應(yīng)來確保安全。
做好前端開發(fā)必須對(duì)HTTP的相關(guān)知識(shí)有所了解,所以我創(chuàng)建了一個(gè)專題前端必備HTTP技能專門收集前端相關(guān)的HTTP知識(shí),歡迎關(guān)注,投稿。
PS:本文翻譯自維基百科,原文地址https://en.wikipedia.org/wiki/Cross-origin_resource_sharing