做者:fredalxin
地址:https://fredal.xin/websocket-...html
最近在建設websocket長鏈接網關,過程當中遇到一件比較奇怪的事情,作下簡單的記錄。java
需求十分的簡單,websocket網關在作權限校驗的時候指望複用現有登陸邏輯的jwt-token。以下圖所示,sso與websocket網關屬於不一樣的二級域名,登陸的jwt-token cookie的domain設置爲*.xx.com。web
因此咱們的指望是瀏覽器與websocket網關進行handshark請求時能夠帶上jwt-token cookie。面試
結果天然是不行的,服務端並無收到來自*.xx.com的cookie。因而開始考慮可能和跨域行爲有關係。spring
CORS 是一種用於解決跨域的w3c標準,全稱爲"跨域資源共享"(Cross-origin resource sharing)。它容許瀏覽器向跨源服務器,發出 XMLHttpRequest 請求,從而克服了 AJAX 只能同源使用的限制。CORS 基於 http 協議關於跨域方面的規定,使用時,客戶端瀏覽器直接異步請求被調用端服務端,在響應頭增長響應的字段,告訴瀏覽器後臺容許跨域。chrome
歸納的說,CORS就是服務端對跨域權限的控制,由一組標準的header來控制客戶端的跨域行爲,不一樣瀏覽器對於CORS的實現均有不一樣。跨域
經常使用的CORS header主要有:瀏覽器
CORS處理請求的流程以下:安全
這裏涉及到的簡單請求和非簡單請求的概念,那麼簡單請求和非簡單請求有什麼區別呢?若請求知足全部下述條件,則該請求可視爲簡單請求:服務器
通過一番簡單的科普,回到咱們的問題上來。瀏覽器對websocket的handshark請求會不會應用同源策略呢。咱們先不回答,先來看看若是CORS應用在websocket上會是什麼樣的。
首先一個websocket的握手鍊接報文大概以下:
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請求的區別是多了兩行header
Upgrade: websocket Connection: Upgrade
顯然它們不屬於CORS安全的header集合,天然瀏覽器會認爲這不是一個"簡單請求"。那麼它會按照發起"預檢請求",隨後根據返回的response header來判斷下一步行爲。此處咱們但願能帶上當前域的cookie,那麼按照CORS標準,咱們須要在服務端作一些配置,讓其支持CORS並帶上Access-Control-Allow-Credentials爲true的response header。
咱們使用的是Netty來構建websocket網關,Netty支持CORS很簡單:
CorsConfig corsConfig = CorsConfigBuilder.forAnyOrigin().allowNullOrigin().allowCredentials().build(); pipeline.addLast(new CorsHandler(corsConfig));
結果是什麼呢?咱們的websocket服務端正確拿到了*.xx.com的cookie,並完成了後續鑑權工做。
因此真相是什麼呢?websocket也須要CORS支持來避免跨域問題麼?
google任何websocket與跨域相關的問題都會告訴你,websocket自己就是支持跨域的,websocket自己沒有同源策略!也就是說,在第一幅圖中,咱們應該不做任何事就能夠把xx.com的cookie帶到ws.xx.com的websocket網關上去,這彷佛和咱們實際狀況不符。
咱們使用的是chrome,後來突發奇想試了下firefox與safari,結論是這二者不用配置任何CORS相關屬性就能夠把cookie帶上。難道這是chrome的一個bug?翻了翻網絡,找到了一個彷佛能夠應徵的bug report:https://bugs.chromium.org/p/c...
近期熱文推薦:
1.600+ 道 Java面試題及答案整理(2021最新版)
2.終於靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!
3.阿里 Mock 工具正式開源,幹掉市面上全部 Mock 工具!
4.Spring Cloud 2020.0.0 正式發佈,全新顛覆性版本!
以爲不錯,別忘了隨手點贊+轉發哦!