?
This document uses PHP Chinese website manual Release
當(dāng)資源請(qǐng)求來自不同域,協(xié)議或端口的資源時(shí),資源會(huì)發(fā)出跨源HTTP請(qǐng)求。例如,http://domain-a.com<img> src
提供的HTML頁面提出了http://domain-b.com/image.jpg的請(qǐng)求。今天網(wǎng)絡(luò)上的許多頁面都會(huì)加載資源,如來自不同域的CSS樣式表,圖像和腳本。
出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源HTTP請(qǐng)求。例如,XMLHttpRequest
并且取遵循同源策略。因此,使用XMLHttpRequest
或提取 的Web應(yīng)用程序只能向自己的域發(fā)出HTTP請(qǐng)求。為了改進(jìn)Web應(yīng)用程序,開發(fā)人員要求瀏覽器供應(yīng)商允許跨域請(qǐng)求。
跨源資源共享(CORS)機(jī)制為Web服務(wù)器提供跨域訪問控制,從而實(shí)現(xiàn)安全的跨域數(shù)據(jù)傳輸?,F(xiàn)代瀏覽器在API容器中使用CORS(例如XMLHttpRequest
或Fetch)來緩解跨源HTTP請(qǐng)求的風(fēng)險(xiǎn)。
本文適用于Web管理員,服務(wù)器開發(fā)人員和前端開發(fā)人員?,F(xiàn)代瀏覽器處理跨源共享的客戶端組件,包括標(biāo)頭和策略實(shí)施。但是這個(gè)新標(biāo)準(zhǔn)意味著服務(wù)器必須處理新的請(qǐng)求和響應(yīng)頭文件。另一篇關(guān)于服務(wù)器開發(fā)人員從服務(wù)器角度討論跨源共享的文章(使用PHP代碼片段)是補(bǔ)充閱讀。
這種跨源共享標(biāo)準(zhǔn)用于為以下項(xiàng)目啟用跨站點(diǎn)HTTP請(qǐng)求:
如上所述,以跨站點(diǎn)的方式調(diào)用XMLHttpRequest
或提取 API。
Web字體(用于@font-face
CSS內(nèi)的跨域字體使用),以便服務(wù)器可以部署TrueType字體,這些字體只能跨站點(diǎn)加載并由允許這樣做的網(wǎng)站使用。
WebGL紋理。
使用繪制到畫布的圖像/視頻幀drawImage
。
樣式表(用于CSSOM訪問)。
腳本(用于非靜音例外)。
本文是跨源資源共享的一般性討論,并包括對(duì)必要HTTP標(biāo)頭的討論。
跨源資源共享標(biāo)準(zhǔn)的工作原理是添加新的HTTP標(biāo)頭,允許服務(wù)器描述允許使用Web瀏覽器讀取該信息的一組原點(diǎn)。此外,對(duì)于可能對(duì)服務(wù)器數(shù)據(jù)產(chǎn)生副作用的HTTP請(qǐng)求方法(特別是針對(duì)除特定MIME類型之外的HTTP方法GET
或針對(duì)POST
某些MIME類型使用的HTTP方法),規(guī)范要求瀏覽器“預(yù)檢”請(qǐng)求,請(qǐng)求來自服務(wù)器與HTTP OPTIONS
請(qǐng)求方法,然后,在從服務(wù)器獲得“批準(zhǔn)”后,使用實(shí)際的HTTP請(qǐng)求方法發(fā)送實(shí)際請(qǐng)求。服務(wù)器還可以通知客戶端“憑證”(包括Cookie和HTTP認(rèn)證數(shù)據(jù))是否應(yīng)該隨請(qǐng)求一起發(fā)送。
后續(xù)章節(jié)討論方案,并提供所使用的HTTP標(biāo)頭的細(xì)目。
在這里,我們提供了三個(gè)場(chǎng)景來說明跨源資源共享如何工作。所有這些示例都使用該XMLHttpRequest
對(duì)象,該對(duì)象可用于在任何支持的瀏覽器中進(jìn)行跨站點(diǎn)調(diào)用。
這些部分包含的JavaScript代碼片段(以及正確處理這些跨站點(diǎn)請(qǐng)求的服務(wù)器代碼的運(yùn)行實(shí)例)可以在http://arunranga.com/examples/access-control/中找到“實(shí)際操作” ,并且將在支持跨站點(diǎn)的瀏覽器中工作XMLHttpRequest
。
從服務(wù)器的角度討論跨源資源共享(包括PHP代碼片段)可以在服務(wù)器端訪問控制(CORS)文章中找到。
有些請(qǐng)求不會(huì)觸發(fā)CORS預(yù)檢。這些在本文中被稱為“簡(jiǎn)單請(qǐng)求”,盡管Fetch規(guī)范(它定義了CORS)不使用該術(shù)語。不會(huì)觸發(fā)CORS預(yù)檢的請(qǐng)求(所謂的“簡(jiǎn)單請(qǐng)求”)是滿足以下所有條件的請(qǐng)求:
唯一允許的方法是:
GET
HEAD
POST
除了由用戶代理自動(dòng)設(shè)置的標(biāo)頭(例如,Connection
,User-Agent
,或任何與所述抓取規(guī)格為“禁止的標(biāo)題名稱”定義名稱其它標(biāo)題的),其允許被手動(dòng)設(shè)置僅標(biāo)頭是那些Fetch規(guī)范將其定義為“CORS安全列表請(qǐng)求標(biāo)頭”,它們是:
Accept
Accept-Language
Content-Language
Content-Type
(但請(qǐng)注意下面的附加要求)
Last-Event-ID
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type
標(biāo)題的唯一允許值是:
application/x-www-form-urlencoded
multipart/form-data
text/plain
沒有事件偵聽器XMLHttpRequestUpload
在請(qǐng)求中使用的任何對(duì)象上注冊(cè)。
ReadableStream
請(qǐng)求中沒有使用對(duì)象。
注意:這些是與Web內(nèi)容已經(jīng)發(fā)布的相同類型的跨站點(diǎn)請(qǐng)求,并且除非服務(wù)器發(fā)送適當(dāng)?shù)臉?biāo)頭,否則不會(huì)向請(qǐng)求者發(fā)布響應(yīng)數(shù)據(jù)。因此,防止跨站點(diǎn)請(qǐng)求偽造的站點(diǎn)對(duì)HTTP訪問控制毫無新意。
注:允許在WebKit每日和Safari瀏覽器技術(shù)預(yù)覽地方上的值的額外限制Accept
,Accept-Language
和Content-Language
頭。如果任何這些頭文件具有“非標(biāo)準(zhǔn)”值,則WebKit / Safari不會(huì)將該請(qǐng)求視為符合“簡(jiǎn)單請(qǐng)求”的條件。除了以下WebKit錯(cuò)誤之外,WebKit / Safari認(rèn)為這些標(biāo)頭的“非標(biāo)準(zhǔn)”值沒有記錄:對(duì)非標(biāo)準(zhǔn)CORS安全列表的請(qǐng)求標(biāo)頭需要預(yù)檢Accept,Accept-Language和Content-Language,允許逗號(hào),簡(jiǎn)單CORS的Accept-Language和Content-Language請(qǐng)求標(biāo)題,以及在簡(jiǎn)單的CORS請(qǐng)求中切換到黑名單模型以獲取受限制的Accept標(biāo)頭。沒有其他瀏覽器實(shí)現(xiàn)這些額外的限制,因?yàn)樗鼈儾皇且?guī)范的一部分。
例如,假設(shè)域上的網(wǎng)頁內(nèi)容http://foo.example
希望調(diào)用域上的內(nèi)容http://bar.other
。這種代碼可以在部署在foo.example上的JavaScript中使用:
var invocation = new XMLHttpRequest();var url = 'http://bar.other/resources/public-data/'; function callOtherDomain() { if(invocation) { invocation.open('GET', url, true); invocation.onreadystatechange = handler; invocation.send(); }}
這將導(dǎo)致客戶端和服務(wù)器之間的簡(jiǎn)單交換,使用CORS頭來處理權(quán)限:
讓我們看看在這種情況下瀏覽器將發(fā)送到服務(wù)器的內(nèi)容,然后讓我們看看服務(wù)器如何響應(yīng):
GET /resources/public-data/ HTTP/1.1Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Referer: http://foo.example/examples/access-control/simpleXSInvocation.html Origin: http://foo.example HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2.0.61 Access-Control-Allow-Origin: * Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml [XML Data]
1 - 10行發(fā)送標(biāo)題。這里需要注意的主要HTTP請(qǐng)求頭是Origin
上面第10行的頭,表示調(diào)用來自域上的內(nèi)容http://foo.example
。
第13 - 22行顯示了域上服務(wù)器的HTTP響應(yīng)http://bar.other
。作為響應(yīng),服務(wù)器發(fā)回一個(gè)Access-Control-Allow-Origin
頭部,如上面第16行所示。使用Origin
頭部和Access-Control-Allow-Origin
顯示訪問控制協(xié)議的最簡(jiǎn)單的用法。在這種情況下,服務(wù)器回應(yīng)一個(gè)Access-Control-Allow-Origin: *
,這意味著資源可以通過任何域以跨站點(diǎn)方式訪問。如果資源所有者http://bar.other
希望將資源的訪問限制為僅來自請(qǐng)求的資源http://foo.example
,則他們將發(fā)回:
Access-Control-Allow-Origin: http://foo.example
請(qǐng)注意,現(xiàn)在除了http://foo.example
(由請(qǐng)求中的ORIGIN:標(biāo)頭標(biāo)識(shí)的,如上面的第10行)之外,沒有任何域可以以跨站點(diǎn)方式訪問資源。該Access-Control-Allow-Origin
頭應(yīng)包含在請(qǐng)求的發(fā)送的值Origin
頭。
與上面討論的“簡(jiǎn)單請(qǐng)求”不同,“preflighted”請(qǐng)求首先通過OPTIONS
方法向另一個(gè)域上的資源發(fā)送HTTP請(qǐng)求,以確定實(shí)際請(qǐng)求是否安全發(fā)送??缯菊?qǐng)求是這樣預(yù)檢的,因?yàn)樗鼈兛赡軙?huì)影響用戶數(shù)據(jù)。
特別是,如果滿足以下任一條件,則會(huì)請(qǐng)求一個(gè)請(qǐng)求:
如果請(qǐng)求使用以下任何一種方法:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH
或者,如果,除了由用戶代理自動(dòng)設(shè)置的標(biāo)頭(例如,Connection
,User-Agent
,或任何與所述抓取規(guī)格為“禁止的標(biāo)題名稱”中定義的名稱其它頭的),該請(qǐng)求包括比其他任何頭那些Fetch規(guī)范將其定義為“CORS安全列表請(qǐng)求標(biāo)頭”,它們是:
Accept
Accept-Language
Content-Language
Content-Type
(但請(qǐng)注意下面的附加要求)
Last-Event-ID
DPR
Downlink
Save-Data
Viewport-Width
Width
或者,如果該Content-Type
頭具有比其他如下的值:
application/x-www-form-urlencoded
multipart/form-data
text/plain
或者,如果XMLHttpRequestUpload
在請(qǐng)求中使用的對(duì)象上注冊(cè)了一個(gè)或多個(gè)事件偵聽器。
或者如果ReadableStream
請(qǐng)求中使用了對(duì)象。
注:允許在WebKit每日和Safari瀏覽器技術(shù)預(yù)覽地方上的值的額外限制Accept
,Accept-Language
和Content-Language
頭。如果這些標(biāo)頭中的任何一個(gè)具有“非標(biāo)準(zhǔn)”值,WebKit / Safari會(huì)預(yù)檢請(qǐng)求。除了以下WebKit錯(cuò)誤之外,WebKit / Safari認(rèn)為這些標(biāo)頭的“非標(biāo)準(zhǔn)”值沒有記錄:對(duì)非標(biāo)準(zhǔn)CORS安全列表的請(qǐng)求標(biāo)頭需要預(yù)檢Accept,Accept-Language和Content-Language,允許逗號(hào),簡(jiǎn)單CORS的Accept-Language和Content-Language請(qǐng)求標(biāo)題,以及在簡(jiǎn)單的CORS請(qǐng)求中切換到黑名單模型以獲取受限制的Accept標(biāo)頭。沒有其他瀏覽器實(shí)現(xiàn)這些額外的限制,因?yàn)樗鼈儾皇且?guī)范的一部分。
以下是一個(gè)將被預(yù)沖的請(qǐng)求示例。
var invocation = new XMLHttpRequest();var url = 'http://bar.other/resources/post-here/';var body = '<?xml version="1.0"?><person><name>Arun</name></person>'; function callOtherDomain(){ if(invocation) { invocation.open('POST', url, true); invocation.setRequestHeader('X-PINGOTHER', 'pingpong'); invocation.setRequestHeader('Content-Type', 'application/xml'); invocation.onreadystatechange = handler; invocation.send(body); }}......
在上面的示例中,第3行創(chuàng)建了一個(gè)XML主體,以便POST
在第8行中發(fā)送請(qǐng)求。另外,在第9行中,設(shè)置了一個(gè)“自定義”(非標(biāo)準(zhǔn))HTTP請(qǐng)求標(biāo)頭X-PINGOTHER: pingpong
。這樣的頭文件不是HTTP / 1.1協(xié)議的一部分,但通常對(duì)Web應(yīng)用程序有用。由于請(qǐng)求使用Content-Type application/xml
,并且由于設(shè)置了自定義標(biāo)頭,所以該請(qǐng)求是預(yù)檢的。
(注意:如下所述,實(shí)際的POST請(qǐng)求不包含Access-Control-Request- *標(biāo)題;它們僅用于OPTIONS請(qǐng)求。)
我們來看看客戶端和服務(wù)器之間的完整交換。第一個(gè)交換是預(yù)檢請(qǐng)求/響應(yīng):
OPTIONS /resources/post-here/ HTTP/1.1Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Origin: http://foo.example Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400 Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain
預(yù)檢請(qǐng)求完成后,發(fā)送真正的請(qǐng)求:
POST /resources/post-here/ HTTP/1.1Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive X-PINGOTHER: pingpong Content-Type: text/xml; charset=UTF-8 Referer: http://foo.example/examples/preflightInvocation.html Content-Length: 55 Origin: http://foo.example Pragma: no-cache Cache-Control: no-cache <?xml version="1.0"?><person><name>Arun</name></person> HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:40 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://foo.example Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 235 Keep-Alive: timeout=2, max=99 Connection: Keep-Alive Content-Type: text/plain [Some GZIP'd payload]
上面的第1-12行代表使用該OPTIONS
方法的預(yù)檢請(qǐng)求。瀏覽器根據(jù)上述JavaScript代碼片段使用的請(qǐng)求參數(shù)確定需要發(fā)送該消息,以便服務(wù)器可以響應(yīng)以實(shí)際請(qǐng)求參數(shù)發(fā)送請(qǐng)求是否可接受。OPTIONS是一個(gè)HTTP / 1.1方法,用于確定來自服務(wù)器的更多信息,并且是一種安全的方法,這意味著它不能用于更改資源。請(qǐng)注意,除OPTIONS請(qǐng)求外,還會(huì)發(fā)送另外兩個(gè)請(qǐng)求標(biāo)頭(分別為第10行和第11行):
Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type
Access-Control-Request-Method
報(bào)頭通知服務(wù)器作為預(yù)檢請(qǐng)求被發(fā)送的實(shí)際請(qǐng)求時(shí),它將被與發(fā)送的一部分POST
請(qǐng)求方法。該Access-Control-Request-Headers
頭通知服務(wù)器發(fā)送實(shí)際的請(qǐng)求時(shí),它將被發(fā)送的X-PINGOTHER
和Content-Type自定義頁眉。服務(wù)器現(xiàn)在有機(jī)會(huì)確定它是否希望在這種情況下接受請(qǐng)求。
上面的第14-26行是服務(wù)器發(fā)回的響應(yīng),表明請(qǐng)求方法(POST
)和請(qǐng)求頭(X-PINGOTHER
)是可接受的。具體來說,我們來看第17-20行:
Access-Control-Allow-Origin: http://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400
服務(wù)器響應(yīng)Access-Control-Allow-Methods
,并說POST
,GET
和OPTIONS
是可行的方法來查詢相關(guān)資源。請(qǐng)注意,此標(biāo)頭與Allow
響應(yīng)標(biāo)頭相似,但在訪問控制的上下文中嚴(yán)格使用。
服務(wù)器也發(fā)送Access-Control-Allow-Headers
一個(gè)值為“ X-PINGOTHER, Content-Type
”,確認(rèn)這些是允許的頭部與實(shí)際的請(qǐng)求一起使用。像Access-Control-Allow-Methods
,Access-Control-Allow-Headers
是可以接受的報(bào)頭的逗號(hào)分隔的列表。
最后,Access-Control-Max-Age
給出以秒為單位的值,可以緩存對(duì)預(yù)檢請(qǐng)求的響應(yīng)多長(zhǎng)時(shí)間,而不發(fā)送其他預(yù)檢請(qǐng)求。在這種情況下,86400秒是24小時(shí)。請(qǐng)注意,每個(gè)瀏覽器都有一個(gè)最大內(nèi)部值,當(dāng)該Access-Control-Max-Age
值較大時(shí)優(yōu)先。
大多數(shù)瀏覽器目前不支持預(yù)先發(fā)送的請(qǐng)求的重定向。如果針對(duì)預(yù)先發(fā)送的請(qǐng)求發(fā)生重定向,則大多數(shù)當(dāng)前瀏覽器將報(bào)告如下的錯(cuò)誤消息。
該請(qǐng)求被重定向到“ https://example.com/foo ”,該請(qǐng)求被禁止用于需要預(yù)檢的跨請(qǐng)求請(qǐng)求。請(qǐng)求需要預(yù)檢,不允許跟蹤跨源重定向
CORS協(xié)議最初需要這種行為,但后來被更改為不再需要它。但是,大多數(shù)瀏覽器尚未實(shí)現(xiàn)此更改并仍顯示最初所需的行為。
因此,除非瀏覽器趕上規(guī)范,否則您可以通過執(zhí)行以下一項(xiàng)或兩項(xiàng)操作來解決此限制:
更改服務(wù)器端行為以避免預(yù)檢和/或避免重定向 - 如果您有控制服務(wù)器的請(qǐng)求正在進(jìn)行
請(qǐng)更改請(qǐng)求,使其不會(huì)產(chǎn)生印前檢查
但是如果不能做出這些改變,那么另一種可能的方式就是:
做一個(gè)簡(jiǎn)單的請(qǐng)求來確定(使用Response.url來獲取API,或者使用XHR.responseURL來確定真正的預(yù)發(fā)光請(qǐng)求最終會(huì)到達(dá)哪個(gè)URL)。
使用從Response.url或XMLHttpRequest.responseURL獲取的URL 在第一步中創(chuàng)建另一個(gè)請(qǐng)求(“真實(shí)”請(qǐng)求)。
但是,如果請(qǐng)求是由于請(qǐng)求中存在Authorization
標(biāo)題而觸發(fā)預(yù)檢的請(qǐng)求,則無法使用上述步驟解決限制。除非您可以控制正在進(jìn)行請(qǐng)求的服務(wù)器,否則您將無法徹底解決此問題。
由兩個(gè)暴露的最有趣的功能XMLHttpRequest
或獲取和CORS是使知道HTTP Cookie和HTTP認(rèn)證信息的“持證”請(qǐng)求的能力。默認(rèn)情況下,在跨站點(diǎn)XMLHttpRequest
或Fetch調(diào)用中,瀏覽器不會(huì)發(fā)送憑據(jù)。調(diào)用時(shí),必須在XMLHttpRequest
對(duì)象或Request
構(gòu)造函數(shù)上設(shè)置特定的標(biāo)志。
在此示例中,最初加載的內(nèi)容http://foo.example
向http://bar.other
設(shè)置了Cookie 的資源發(fā)出簡(jiǎn)單的GET請(qǐng)求。foo.example上的內(nèi)容可能包含JavaScript,如下所示:
var invocation = new XMLHttpRequest();var url = 'http://bar.other/resources/credentialed-content/'; function callOtherDomain(){ if(invocation) { invocation.open('GET', url, true); invocation.withCredentials = true; invocation.onreadystatechange = handler; invocation.send(); }}
第7行顯示了XMLHttpRequest
必須設(shè)置的標(biāo)志,以便使用Cookie進(jìn)行調(diào)用,即withCredentials
布爾值。默認(rèn)情況下,調(diào)用不使用Cookies。由于這是一個(gè)簡(jiǎn)單的GET
請(qǐng)求,這不是預(yù)檢,但瀏覽器將拒絕不具有任何的響應(yīng)Access-Control-Allow-Credentials: true
報(bào)頭,并沒有提供給調(diào)用web內(nèi)容的響應(yīng)。
以下是客戶端和服務(wù)器之間的示例交換:
GET /resources/access-control-with-credentials/ HTTP/1.1Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Referer: http://foo.example/examples/credential.html Origin: http://foo.example Cookie: pageAccess=2 HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:34:52 GMT Server: Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2 X-Powered-By: PHP/5.2.6 Access-Control-Allow-Origin: http://foo.example Access-Control-Allow-Credentials: true Cache-Control: no-cache Pragma: no-cache Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 106 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain [text/plain payload]
雖然第11行包含http://bar.other
指向內(nèi)容的Cookie ,但如果bar.other沒有響應(yīng)Access-Control-Allow-Credentials: true
(第19行),則響應(yīng)將被忽略并且不會(huì)提供給Web內(nèi)容。
在響應(yīng)有證書請(qǐng)求時(shí),服務(wù)器必須在Access-Control-Allow-Origin
標(biāo)題的值中指定一個(gè)源,而不是指定“ *
”通配符。
由于上述示例中的請(qǐng)求標(biāo)頭包含Cookie
標(biāo)頭,因此如果Access-Control-Allow-Origin
標(biāo)頭的值為“*” ,則請(qǐng)求將失敗。但它不會(huì)失敗:因?yàn)?code>Access-Control-Allow-Origin頭部的值是“ http://foo.example
”(實(shí)際起源)而不是“ *
”通配符,所以證書認(rèn)知內(nèi)容將返回到調(diào)用的Web內(nèi)容。
請(qǐng)注意,上述Set-Cookie
示例中的響應(yīng)標(biāo)頭還設(shè)置了另一個(gè)cookie。如果發(fā)生故障,則會(huì)引發(fā)異常(取決于所使用的API)。
本部分列出服務(wù)器為“跨源資源共享”規(guī)范定義的訪問控制請(qǐng)求發(fā)送的HTTP響應(yīng)頭。上一節(jié)將概述這些實(shí)際情況。
返回的資源可能有一個(gè)Access-Control-Allow-Origin
標(biāo)題,其語法如下:
Access-Control-Allow-Origin: <origin> | *
該origin
參數(shù)指定可以訪問資源的URI。瀏覽器必須執(zhí)行此操作。對(duì)于沒有憑據(jù)的請(qǐng)求,服務(wù)器可以指定“*”作為通配符,從而允許任何來源訪問資源。
例如,要允許http://mozilla.org訪問資源,您可以指定:
Access-Control-Allow-Origin: http://mozilla.org
如果服務(wù)器指定的是原始主機(jī)而不是“*”,那么它也可以在Vary響應(yīng)頭中包含Origin來向客戶機(jī)指出服務(wù)器響應(yīng)將根據(jù)Origin請(qǐng)求頭的值而不同。
該Access-Control-Expose-Headers
標(biāo)題即可讓所有瀏覽器都允許訪問的服務(wù)器白名單頭。例如:
Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
這允許X-My-Custom-Header
和X-Another-Custom-Header
標(biāo)題暴露給瀏覽器。
Access-Control-Max-Age
報(bào)頭指示預(yù)檢請(qǐng)求的結(jié)果多久可以被緩存。有關(guān)預(yù)檢請(qǐng)求的示例,請(qǐng)參閱上述示例。
Access-Control-Max-Age: <delta-seconds>
該delta-seconds
參數(shù)表示可以緩存結(jié)果的秒數(shù)。
Access-Control-Allow-Credentials
報(bào)頭指示是否對(duì)所述請(qǐng)求的響應(yīng)可以在被暴露credentials
標(biāo)記為真。當(dāng)作為對(duì)預(yù)檢請(qǐng)求的響應(yīng)的一部分使用時(shí),這指示是否可以使用憑證進(jìn)行實(shí)際請(qǐng)求。請(qǐng)注意,簡(jiǎn)單的GET
請(qǐng)求不是預(yù)檢的,所以如果請(qǐng)求使用憑證的資源,如果此資源不與資源一起返回,瀏覽器將忽略該響應(yīng),并且不會(huì)返回到Web內(nèi)容。
Access-Control-Allow-Credentials: true
以上討論了認(rèn)證請(qǐng)求。
該Access-Control-Allow-Methods
頭指定訪問資源時(shí)所允許的一種或多種方法。這用于響應(yīng)預(yù)檢請(qǐng)求。上面討論了預(yù)先請(qǐng)求的條件。
Access-Control-Allow-Methods: <method>[, <method>]*
上面給出了一個(gè)預(yù)檢請(qǐng)求的示例,其中包括將此標(biāo)頭發(fā)送給瀏覽器的示例。
所述Access-Control-Allow-Headers
報(bào)頭在響應(yīng)用來預(yù)檢請(qǐng)求,以指示在進(jìn)行實(shí)際請(qǐng)求時(shí)HTTP標(biāo)頭都可以使用。
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
本節(jié)列出客戶端在發(fā)出HTTP請(qǐng)求時(shí)可能使用的標(biāo)題,以便利用跨源共享功能。請(qǐng)注意,在調(diào)用服務(wù)器時(shí)會(huì)為您設(shè)置這些標(biāo)頭。使用跨站點(diǎn)XMLHttpRequest
功能的開發(fā)人員不必以編程方式設(shè)置任何跨源共享請(qǐng)求標(biāo)頭。
Origin
報(bào)頭指示跨站點(diǎn)接入請(qǐng)求或預(yù)檢請(qǐng)求的來源。
Origin: <origin>
起源是一個(gè)URI,表示請(qǐng)求發(fā)起的服務(wù)器。它不包含任何路徑信息,但僅包含服務(wù)器名稱。
注:在origin
可以為空字符串; 例如,如果源是data
URL ,這很有用。
請(qǐng)注意,在任何訪問控制請(qǐng)求中,始終發(fā)送Origin
標(biāo)題。
該Access-Control-Request-Method
發(fā)出的預(yù)檢要求,讓服務(wù)器知道實(shí)際的請(qǐng)求時(shí)會(huì)怎樣使用HTTP方法時(shí)使用。
Access-Control-Request-Method: <method>
這種用法的例子可以在上面找到。
該Access-Control-Request-Headers
發(fā)出的預(yù)檢要求,讓服務(wù)器知道什么實(shí)際的請(qǐng)求時(shí)HTTP標(biāo)頭的時(shí)候會(huì)用到頭使用。
Access-Control-Request-Headers: <field-name>[, <field-name>]*
這種用法的例子可以在上面找到。
規(guī)范 | 狀態(tài) | 評(píng)論 |
---|---|---|
在該規(guī)范中獲取'CORS'的定義。 | 生活水平 | 新定義; 取代W3C CORS規(guī)范。 |
特征 | Chrome | Edge | 火狐 | Internet Explorer | Opera | 蘋果瀏覽器 |
---|---|---|---|---|---|---|
基本支持 | 4 | 12 | 3.5 | 10 | 12 | 4 |
特征 | Android的 | 適用于Android的Chrome | Edge 移動(dòng) | 適用于Android的Firefox | IE手機(jī) | Opera Android | iOS Safari |
---|---|---|---|---|---|---|---|
基本支持 | 2.1 | (是) | (是) | 1.0 | (是) | 12 | 3.2 |
Internet Explorer 8和9通過該XDomainRequest
對(duì)象公開CORS ,但在IE 10中完全實(shí)現(xiàn)。
盡管Firefox 3.5引入了對(duì)跨站點(diǎn)XMLHttpRequests和Web字體的支持,但某些請(qǐng)求在新版本之前是有限的。具體來說,F(xiàn)irefox 7引入了WebGL紋理的跨站點(diǎn)HTTP請(qǐng)求功能,并且Firefox 9添加了對(duì)使用的畫布上繪制的圖像的支持drawImage
。
代碼示例顯示XMLHttpRequest
和跨源資源共享
跨服務(wù)器端透視資源共享(PHP等)
跨源資源共享規(guī)范
XMLHttpRequest
取API
與所有(現(xiàn)代)瀏覽器一起使用CORS
使用CORS - HTML5巖石
堆棧溢出回答與“如何”信息處理常見問題:
如何避免CORS預(yù)檢
如何使用CORS代理來解決“無訪問控制 - 允許源標(biāo)頭”
如何解決“Access-Control-Allow-Origin頭部不能是通配符”