日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CORS——跨域请求那些事儿

發(fā)布時(shí)間:2023/12/9 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CORS——跨域请求那些事儿 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【本期嘉賓介紹】睿得,具有多年研發(fā)、運(yùn)維、安全等IT相關(guān)從業(yè)經(jīng)歷。目前從事CDN、存儲(chǔ)、視頻直播點(diǎn)播的技術(shù)支持。喜愛鉆研,喜愛編碼,喜愛分享。


在日常的項(xiàng)目開發(fā)時(shí)會(huì)不可避免的需要進(jìn)行跨域操作,而在實(shí)際進(jìn)行跨域請(qǐng)求時(shí),經(jīng)常會(huì)遇到類似 No 'Access-Control-Allow-Origin' header is present on the requested resource.這樣的報(bào)錯(cuò)。

這樣的錯(cuò)誤,一般是由于CORS跨域驗(yàn)證機(jī)制設(shè)置不正確導(dǎo)致的,本文將詳細(xì)講解CORS跨域驗(yàn)證機(jī)制的原理,讓您輕松掌握CORS跨域設(shè)置的使用方法,安全、方便的進(jìn)行前端開發(fā)。

什么是CORS

CORS(Cross-Origin Resource Sharing 跨源資源共享),當(dāng)一個(gè)請(qǐng)求url的協(xié)議、域名、端口三者之間任意一與當(dāng)前頁面地址不同即為跨域。

例如最常見的,在一個(gè)域名下的網(wǎng)頁中,調(diào)用另一個(gè)域名中的資源。

相對(duì)于上面這種靜態(tài)的調(diào)用方式,還可以通過Ajax技術(shù)來動(dòng)態(tài)發(fā)起跨域請(qǐng)求。例如如下的方式,利用XMLHttpRequest對(duì)象發(fā)送一個(gè)GET請(qǐng)求,獲取另一個(gè)域名下的圖片內(nèi)容。

<!DOCTYPE html> <html><head>CORS Test</head><body><div id="img_Div"></div><script type="text/javascript"> //XmlHttpRequest對(duì)象 function createXmlHttpRequest(){ if(window.ActiveXObject){ //如果是IE瀏覽器 return new ActiveXObject("Microsoft.XMLHTTP"); }else if(window.XMLHttpRequest){ //非IE瀏覽器 return new XMLHttpRequest(); } } function getFile() {var img_Container = document.getElementById("img_Div");var xhr = createXmlHttpRequest();xhr.open('GET', 'http://oss.youkouyang.com/1.jpg', true);xhr.setRequestHeader('Content-Type', 'image/jpeg');xhr.responseType = "blob";xhr.onload = function() {if (this.status == 200) {var blob = this.response;var img = document.createElement("img");img.onload = function(e) {window.URL.revokeObjectURL(img.src); };img.src = window.URL.createObjectURL(blob);img_Container.appendChild(img); }}xhr.send(null);}</script><div class="row"><input type="button" onclick="getFile()" value="Get" /></div></body> </html>??

CORS的作用

為了改善網(wǎng)絡(luò)應(yīng)用程序,開發(fā)人員要求瀏覽器供應(yīng)商允許跨域請(qǐng)求。跨域請(qǐng)求主要用于:

  • 調(diào)用XMLHttpRequest或fetchAPI通過跨站點(diǎn)方式訪問資源
  • 網(wǎng)絡(luò)字體,例如Bootstrap(通過CSS使用@font-face 跨域調(diào)用字體)
  • 通過canvas標(biāo)簽,繪制圖表和視頻。

CORS的安全隱患

跨域請(qǐng)求和Ajax技術(shù)都會(huì)極大地提高頁面的體驗(yàn),但同時(shí)也會(huì)帶來安全的隱患,其中最主要的隱患來自于CSRF(Cross-site request forgery)跨站請(qǐng)求偽造。

CSRF攻擊的大致原理是:

  • 用戶通過瀏覽器,訪問正常網(wǎng)站A(例如某銀行),通過用戶的身份認(rèn)證(比如用戶名/密碼)成功A網(wǎng)站。
  • 網(wǎng)站A產(chǎn)生Cookie信息并返回給用戶的瀏覽器;?
  • 用戶保持A網(wǎng)站頁面登錄狀態(tài),在同一瀏覽器中,打開一個(gè)新的TAB頁訪問惡意網(wǎng)站B;
  • 網(wǎng)站B接收到用戶請(qǐng)求后,返回一些攻擊性代碼,請(qǐng)求A網(wǎng)站的資源(例如轉(zhuǎn)賬請(qǐng)求);
  • 瀏覽器執(zhí)行惡意代碼,在用戶不知情的情況下攜帶Cookie信息,向網(wǎng)站A發(fā)出請(qǐng)求。
  • 網(wǎng)站A根據(jù)用戶的Cookie信息核實(shí)用戶身份(此時(shí)用戶在A網(wǎng)站是已登錄狀態(tài)),A網(wǎng)站會(huì)處理該請(qǐng)求,導(dǎo)致來自網(wǎng)站B的惡意請(qǐng)求被執(zhí)行。
  • CORS驗(yàn)證機(jī)制

    出于安全原因,瀏覽器限制從腳本中發(fā)起的跨域HTTP請(qǐng)求。默認(rèn)的安全限制為同源策略, 即JavaScript或Cookie只能訪問同域下的內(nèi)容。
    W3C推薦了一種跨域的訪問驗(yàn)證的機(jī)制,即CORS(Cross-Origin Resource Sharing 跨源資源共享)。
    這種機(jī)制讓W(xué)eb應(yīng)用服務(wù)器能支持跨站訪問控制,使跨站數(shù)據(jù)傳輸更加安全,減輕跨域HTTP請(qǐng)求的風(fēng)險(xiǎn)。
    CORS驗(yàn)證機(jī)制需要客戶端和服務(wù)端協(xié)同處理。

    CORS瀏覽器支持情況

    目前主流瀏覽器都已基本提供對(duì)跨域資源共享的支持,移動(dòng)端瀏覽器也幾乎全部支持。


    客戶端處理機(jī)制

    基于上述的CSRF的風(fēng)險(xiǎn),各主流的瀏覽器都會(huì)對(duì)動(dòng)態(tài)的跨域請(qǐng)求進(jìn)行特殊的驗(yàn)證處理。驗(yàn)證處理分為簡單請(qǐng)求驗(yàn)證處理和預(yù)先請(qǐng)求驗(yàn)證處理。

    簡單請(qǐng)求

    當(dāng)請(qǐng)求同時(shí)滿足下面兩個(gè)條件時(shí),瀏覽器會(huì)直接發(fā)送GET請(qǐng)求,在同一個(gè)請(qǐng)求中做跨域權(quán)限的驗(yàn)證。

    請(qǐng)求方法是下列之一:

    • GET
    • HEAD
    • POST

    請(qǐng)求頭中的Content-Type請(qǐng)求頭的值是下列之一:

    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

    簡單請(qǐng)求時(shí),瀏覽器會(huì)直接發(fā)送跨域請(qǐng)求,并在請(qǐng)求頭中攜帶Origin 的header,表明這是一個(gè)跨域的請(qǐng)求。
    服務(wù)器端接到請(qǐng)求后,會(huì)根據(jù)自己的跨域規(guī)則,通過Access-Control-Allow-Origin和Access-Control-Allow-Methods響應(yīng)頭,來返回驗(yàn)證結(jié)果。
    如果驗(yàn)證成功,則會(huì)直接返回訪問的資源內(nèi)容。


    如果驗(yàn)證失敗,則返回403的狀態(tài)碼,不會(huì)返回跨域請(qǐng)求的資源內(nèi)容。


    可以通過瀏覽器的Console查看具體的驗(yàn)證失敗原因

    預(yù)先請(qǐng)求

    當(dāng)請(qǐng)求滿足下面任意一個(gè)條件時(shí),瀏覽器會(huì)先發(fā)送一個(gè)OPTION請(qǐng)求,用來與目標(biāo)域名服務(wù)器協(xié)商決定是否可以發(fā)送實(shí)際的跨域請(qǐng)求。

    請(qǐng)求方法不是下列之一:

    • GET
    • HEAD
    • POST

    請(qǐng)求頭中的Content-Type請(qǐng)求頭的值不是下列之一:

    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

    ?

    瀏覽器在發(fā)現(xiàn)頁面中有上述條件的動(dòng)態(tài)跨域請(qǐng)求的時(shí)候,并不會(huì)立即執(zhí)行對(duì)應(yīng)的請(qǐng)求代碼,而是會(huì)先發(fā)送Preflighted requests(預(yù)先驗(yàn)證請(qǐng)求),Preflighted requests是一個(gè)OPTION請(qǐng)求,用于詢問要被跨域訪問的服務(wù)器,是否允許當(dāng)前域名下的頁面發(fā)送跨域的請(qǐng)求。?

    ?

    OPTIONS請(qǐng)求頭部中會(huì)包含以下頭部:Origin、Access-Control-Request-Method、Access-Control-Request-Headers。
    服務(wù)器收到OPTIONS請(qǐng)求后,設(shè)置Access-Control-Allow-Origin、Access-Control-Allow-Method、Access-Control-Allow-Headers頭部與瀏覽器溝通來判斷是否允許這個(gè)請(qǐng)求。
    如果Preflighted requests驗(yàn)證通過,瀏覽器才會(huì)發(fā)送真正的跨域請(qǐng)求。
      

    如果Preflighted requests驗(yàn)證失敗,則會(huì)返回403狀態(tài),瀏覽器不會(huì)發(fā)送真正的跨域請(qǐng)求。
    ?

    ?可以通過瀏覽器的Console查看具體的驗(yàn)證失敗原因

    ?

    帶認(rèn)證的請(qǐng)求

    默認(rèn)情況下,跨源請(qǐng)求不提供憑據(jù)(cookie、HTTP認(rèn)證及客戶端SSL證明等)。通過將withCredentials屬性設(shè)置為true,可以指定某個(gè)請(qǐng)求應(yīng)該發(fā)送憑據(jù)。
    xhr.withCredentials = true;
    如果服務(wù)器接收帶憑據(jù)的請(qǐng)求,會(huì)用下面的HTTP頭部來響應(yīng)。
    Access-Control-Allow-Credentials: true
    服務(wù)器還可以在Preflight響應(yīng)中發(fā)送這個(gè)HTTP頭部,表示允許源發(fā)送帶憑據(jù)的請(qǐng)求。


    如果發(fā)送的是帶憑據(jù)的請(qǐng)求,但服務(wù)器的響應(yīng)中沒有包含這個(gè)頭,那么瀏覽器就不會(huì)把響應(yīng)交給JavaScript(responseText中將是空字符串,size為0)。

    注意,當(dāng)withCredentials屬性設(shè)置為true,需要response header中的'Access-Control-Allow-Origin'為一個(gè)確定的域名,而不能使用'*'這樣的通配符。

    服務(wù)端處理機(jī)制

    服務(wù)器端對(duì)于跨域請(qǐng)求的處理流程如下:

  • 首先查看http頭部有無origin字段;
  • 如果沒有,或者不允許,直接當(dāng)成普通請(qǐng)求處理,結(jié)束;
  • 如果有并且是允許的,那么再看是否是preflight(method=OPTIONS);
  • 如果不是preflight(簡單請(qǐng)求),就返回Allow-Origin、Allow-Credentials等,并返回正常內(nèi)容。
  • 如果是preflight(預(yù)先請(qǐng)求),就返回Allow-Headers、Allow-Methods等,內(nèi)容為空;
  • HTTP Header

    Request header

    Origin

    Origin頭在跨域請(qǐng)求或預(yù)先請(qǐng)求中,標(biāo)明發(fā)起跨域請(qǐng)求的源域名。

    Access-Control-Request-Method

    Access-Control-Request-Method頭用于表明跨域請(qǐng)求使用的實(shí)際HTTP方法

    Access-Control-Request-Headers

    Access-Control-Request-Headers用于在預(yù)先請(qǐng)求時(shí),告知服務(wù)器要發(fā)起的跨域請(qǐng)求中會(huì)攜帶的請(qǐng)求頭信息

    Response header

    Access-Control-Allow-Origin

    Access-Control-Allow-Origin頭中攜帶了服務(wù)器端驗(yàn)證后的允許的跨域請(qǐng)求域名,可以是一個(gè)具體的域名或是一個(gè)*(表示任意域名)。簡單請(qǐng)求時(shí),瀏覽器會(huì)根據(jù)此響應(yīng)頭的內(nèi)容決定是否給腳本返回相應(yīng)內(nèi)容,預(yù)先驗(yàn)證請(qǐng)求時(shí),瀏覽器會(huì)根據(jù)此響應(yīng)頭決定是否發(fā)送實(shí)際的跨域請(qǐng)求。

    Access-Control-Expose-Headers

    Access-Control-Expose-Headers頭用于允許返回給跨域請(qǐng)求的響應(yīng)頭列表,在列表中的響應(yīng)頭的內(nèi)容,才可以被瀏覽器訪問。

    Access-Control-Max-Age

    Access-Control-Max-Age用于告知瀏覽器可以將預(yù)先檢查請(qǐng)求返回結(jié)果緩存的時(shí)間,在緩存有效期內(nèi),瀏覽器會(huì)使用緩存的預(yù)先檢查結(jié)果判斷是否發(fā)送跨域請(qǐng)求。

    Access-Control-Allow-Credentials

    Access-Control-Allow-Credentials用于告知瀏覽器當(dāng)withCredentials屬性設(shè)置為true時(shí),是否可以顯示跨域請(qǐng)求返回的內(nèi)容。簡單請(qǐng)求時(shí),瀏覽器會(huì)根據(jù)此響應(yīng)頭決定是否顯示響應(yīng)的內(nèi)容。預(yù)先驗(yàn)證請(qǐng)求時(shí),瀏覽器會(huì)根據(jù)此響應(yīng)頭決定在發(fā)送實(shí)際跨域請(qǐng)求時(shí),是否攜帶認(rèn)證信息。

    Access-Control-Allow-Methods

    Access-Control-Allow-Methods用于告知瀏覽器可以在實(shí)際發(fā)送跨域請(qǐng)求時(shí),可以支持的請(qǐng)求方法,可以是一個(gè)具體的方法列表或是一個(gè)*(表示任意方法)。簡單請(qǐng)求時(shí),瀏覽器會(huì)根據(jù)此響應(yīng)頭的內(nèi)容決定是否給腳本返回相應(yīng)內(nèi)容,預(yù)先驗(yàn)證請(qǐng)求時(shí),瀏覽器會(huì)根據(jù)此響應(yīng)頭決定是否發(fā)送實(shí)際的跨域請(qǐng)求。

    Access-Control-Allow-Headers

    Access-Control-Allow-Headers用于告知瀏覽器可以在實(shí)際發(fā)送跨域請(qǐng)求時(shí),可以支持的請(qǐng)求頭,可以是一個(gè)具體的請(qǐng)求頭列表或是一個(gè)*(表示任意請(qǐng)求頭)。簡單請(qǐng)求時(shí),瀏覽器會(huì)根據(jù)此響應(yīng)頭的內(nèi)容決定是否給腳本返回相應(yīng)內(nèi)容,預(yù)先驗(yàn)證請(qǐng)求時(shí),瀏覽器會(huì)根據(jù)此響應(yīng)頭決定是否發(fā)送實(shí)際的跨域請(qǐng)求。?

    配置CORS規(guī)則

    nginx上的CORS配置

    OSS上的CORS配置?

    CDN上的CORS配置

    注意:由于CDN的緩存特性,CDN配合OSS時(shí),需要在CDN中設(shè)置CORS配置。


    總結(jié)

    以上是生活随笔為你收集整理的CORS——跨域请求那些事儿的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。