<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          關(guān)于 websocket 跨域的一個(gè)奇怪問(wèn)題…

          共 3053字,需瀏覽 7分鐘

           ·

          2021-05-05 11:34

          點(diǎn)擊上方藍(lán)色“小哈學(xué)Java”,選擇“設(shè)為星標(biāo)

          回復(fù)“資源”獲取獨(dú)家整理的學(xué)習(xí)資料!


          作者:fredalxin
          地址:https://fredal.xin/websocket-cors-problem

          最近在建設(shè)websocket長(zhǎng)連接網(wǎng)關(guān),過(guò)程中遇到一件比較奇怪的事情,做下簡(jiǎn)單的記錄。

          需求十分的簡(jiǎn)單,websocket網(wǎng)關(guān)在做權(quán)限校驗(yàn)的時(shí)候期望復(fù)用現(xiàn)有登錄邏輯的jwt-token。如下圖所示,sso與websocket網(wǎng)關(guān)屬于不同的二級(jí)域名,登錄的jwt-token cookie的domain設(shè)置為*.xx.com。

          所以我們的期望是瀏覽器與websocket網(wǎng)關(guān)進(jìn)行handshark請(qǐng)求時(shí)可以帶上jwt-token cookie。

          結(jié)果自然是不行的,服務(wù)端并沒(méi)有收到來(lái)自*.xx.com的cookie。于是開(kāi)始考慮可能和跨域行為有關(guān)系。

          CORS

          CORS 是一種用于解決跨域的w3c標(biāo)準(zhǔn),全稱為"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務(wù)器,發(fā)出 XMLHttpRequest 請(qǐng)求,從而克服了 AJAX 只能同源使用的限制。

          CORS 基于 http 協(xié)議關(guān)于跨域方面的規(guī)定,使用時(shí),客戶端瀏覽器直接異步請(qǐng)求被調(diào)用端服務(wù)端,在響應(yīng)頭增加響應(yīng)的字段,告訴瀏覽器后臺(tái)允許跨域。

          概括的說(shuō),CORS就是服務(wù)端對(duì)跨域權(quán)限的控制,由一組標(biāo)準(zhǔn)的header來(lái)控制客戶端的跨域行為,不同瀏覽器對(duì)于CORS的實(shí)現(xiàn)均有不同。

          常用的CORS header主要有:

          • Access-Control-Allow-Origin :指示請(qǐng)求的資源能共享給哪些域,可以是具體的域名或者*表示所有域。
          • Access-Control-Allow-Credentials :指示當(dāng)請(qǐng)求的憑證標(biāo)記為 true 時(shí),是否響應(yīng)該請(qǐng)求。
          • Access-Control-Allow-Headers :用在對(duì)預(yù)請(qǐng)求的響應(yīng)中,指示實(shí)際的請(qǐng)求中可以使用哪些 HTTP 頭。
          • Access-Control-Allow-Methods:指定對(duì)預(yù)請(qǐng)求的響應(yīng)中,哪些 HTTP 方法允許訪問(wèn)請(qǐng)求的資源。

          CORS處理請(qǐng)求的流程如下:

          1. 判斷當(dāng)前請(qǐng)求是否簡(jiǎn)單請(qǐng)求。
          2. 如果不是簡(jiǎn)單請(qǐng)求,則會(huì)使用OPTIONS方法先發(fā)起一個(gè)預(yù)檢請(qǐng)求(PreFlight),預(yù)檢請(qǐng)求通過(guò)返回的response里設(shè)置了對(duì)應(yīng)的header并匹配上了才會(huì)進(jìn)行下一步具體的請(qǐng)求。
          3. 預(yù)檢請(qǐng)求后會(huì)發(fā)起實(shí)際請(qǐng)求,但會(huì)根據(jù)返回的response header來(lái)決定請(qǐng)求行為,例如根據(jù)服務(wù)端設(shè)置的Access-Control-Allow-Credentials值來(lái)決定請(qǐng)求是否攜帶當(dāng)前域的cookie。

          這里涉及到的簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求的概念,那么簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求有什么區(qū)別呢?

          若請(qǐng)求滿足所有下述條件,則該請(qǐng)求可視為簡(jiǎn)單請(qǐng)求:

          1. 使用了下列 HTTP 方法:GET、HEAD、POST。
          2. 只用了以下header:Accept、Accept-Language、Content-Language、Content-Type(有額外限制)、DPR、Downlink、Save-Data、Viewport-Width、Width。
          3. 請(qǐng)求中的任意XMLHttpRequestUpload 對(duì)象均沒(méi)有注冊(cè)任何事件監(jiān)聽(tīng)器;XMLHttpRequestUpload 對(duì)象可以使用 XMLHttpRequest.upload 屬性訪問(wèn)。
          4. 請(qǐng)求中沒(méi)有使用 ReadableStream 對(duì)象。

          經(jīng)過(guò)一番簡(jiǎn)單的科普,回到我們的問(wèn)題上來(lái)。瀏覽器對(duì)websocket的handshark請(qǐng)求會(huì)不會(huì)應(yīng)用同源策略呢。我們先不回答,先來(lái)看看如果CORS應(yīng)用在websocket上會(huì)是什么樣的。

          首先一個(gè)websocket的握手連接報(bào)文大概如下:

          GET / HTTP/1.1

          Upgrade: websocket

          Connection: Upgrade

          Host: ws.xx.com

          Origin: http://www.xx.com

          Sec-WebSocket-Key: sB9cRrP/a9NdMgdcy2VJFX==

          Sec-WebSocket-Version: 11

          它和普通HTTP請(qǐng)求的區(qū)別是多了兩行header

          Upgrade: websocket

          Connection: Upgrade

          顯然它們不屬于CORS安全的header集合,自然瀏覽器會(huì)認(rèn)為這不是一個(gè)"簡(jiǎn)單請(qǐng)求"。那么它會(huì)按照發(fā)起"預(yù)檢請(qǐng)求",隨后根據(jù)返回的response header來(lái)判斷下一步行為。此處我們希望能帶上當(dāng)前域的cookie,那么按照CORS標(biāo)準(zhǔn),我們需要在服務(wù)端做一些配置,讓其支持CORS并帶上Access-Control-Allow-Credentials為true的response header。

          我們使用的是Netty來(lái)構(gòu)建websocket網(wǎng)關(guān),Netty支持CORS很簡(jiǎn)單:

          CorsConfig corsConfig = CorsConfigBuilder.forAnyOrigin().allowNullOrigin().allowCredentials().build();

          pipeline.addLast(new CorsHandler(corsConfig));

          結(jié)果是什么呢?我們的websocket服務(wù)端正確拿到了*.xx.com的cookie,并完成了后續(xù)鑒權(quán)工作。

          websocket需要CORS么?

          所以真相是什么呢?websocket也需要CORS支持來(lái)避免跨域問(wèn)題么?

          google任何websocket與跨域相關(guān)的問(wèn)題都會(huì)告訴你,websocket本身就是支持跨域的,websocket本身沒(méi)有同源策略!也就是說(shuō),在第一幅圖中,我們應(yīng)該不作任何事就可以把xx.com的cookie帶到ws.xx.com的websocket網(wǎng)關(guān)上去,這似乎和我們實(shí)際情況不符。

          我們使用的是chrome,后來(lái)突發(fā)奇想試了下firefox與safari,結(jié)論是這兩者不用配置任何CORS相關(guān)屬性就可以把cookie帶上。難道這是chrome的一個(gè)bug?翻了翻網(wǎng)絡(luò),找到了一個(gè)似乎可以應(yīng)征的bug report:https://bugs.chromium.org/p/chromium/issues/detail?id=947413

          1. 2021 年 4 月程序員工資統(tǒng)計(jì),又拖后腿了……

          2. Java 日志的心路歷程

          3. 知乎高贊:有一個(gè)傻X導(dǎo)師是種怎樣的體驗(yàn)?

          4. 類加載常見(jiàn)錯(cuò)誤總結(jié),寫(xiě)得非常好!

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  午夜美女内射黄操操射精网站大胸操逼 | 成人片无码免费 | 中文字幕有码无码人妻aV蜜桃 | 麻豆精品三级电影 | 97操操操 |