發現問題
由於這是前人寫的代碼,出現問題時沒有太多實現邏輯和記憶可參考。
測試環境在某些時候接口會報錯 413 Request Entity Too Large
, 初步觀察是由於 Cookie 帶有重復的授權信息導致。
導致問題的原因
同一個 host 的不同端口下有不同的應用創建不同的 Cookie, 當某個 API 發起請求時,會帶上所有應用的 Cookie,導致 Cookie 長度過大。
進入一同個 IP 下的某端口登錄應用,這時候會向瀏覽器寫入 Cookie。
隨着不同端口的應用越來越多,存儲的 Cookie 越來越多。
當某個 API 發起請求時,會帶上所有應用的 Cookie,導致 Cookie 長度過大。
達到一定程序時,就會觸發 http 服務的 header 長度限制,導致請求失敗。
瀏覽器演示
postman 演示
為什么開發環境沒有發現此問題
- 不同的人開發不同的項目,不會造成多個項目的 Cookie 累加的情況
- 有 localhost/127.0.0.1/192.x.x.x 可以訪問同一個項目
- 當正常退出時 Cookie 會被清除
疑問
Cookie 是前端寫的后端寫的
為什么會有這個疑問?因為都知道前后端都可以寫 Cookie,並且后端可以決定是否攜帶 Cookie。那么如果假設這個 Cookie 就是后端寫的,那這個問題就應該由后端去解決。
從接口 Response 信息以及前端代碼 Cookies.set 相關代碼基本可以確定 Cookie 是前端寫入的。
是否后端要求的就是當前所需的實現呢(攜帶其他端口下的 Cookie)
如果是,那么這個問題也應該由后端去解決。
根據經驗,我們先假設不是。
假設依據:
- 存在有 Authorization/Blade-Auth 類似授權字段
- 不包含其他端口 Cookie 時系統也可正常使用
- 攜帶其他端口的 Cookie 是 rfc 規范規定的,
Cookie 不提供端口隔離
同時存在多個類似授權的 header
查看 API 的請求報文,可以發現以下 3 個類似授權的 header:
- Authorization: xxx
- Blade-Auth: xxx
- Cookie: xxx
那么問題來了,這三個字段有什么不同?到底哪個是用於授權的?
由於存在 Authorization/Blade-Auth 字段,先假設 Cookie 是沒有用的,或者 Cookie 只是用於暫存授權信息。
觀察請求報文,Blade-Auth 中的值其實就是 Cookie 中的某一條目的值,所以如果 Blade-Auth 是授權字段,則此 Cookie 可以省略。
通過代碼基本確定 Cookie 只是用於暫存授權信息。
PS: 當我去問后端到底是用哪個字段做的授權時,后端說他去看代碼很麻煩,讓我前端自己去測試。我說我可以測試出來帶哪個參數行,哪個參數不行,但授權服務不是我寫的,我沒有保證權。他還是拒絕告訴我這個字段。好吧。
假設通過去除 Cookie 的方案,是否造成新的問題
假設去除 Cookie ,后端接口可以使用成功嗎?
產生找到一個帶授權的 GET 請求,居然不帶任何授權字段都能通過,難道后端故意對 GET 放寬了權限?
於是我拿到了個創建助手的 POST 請求,同樣不帶任何授權字段都可以創建成功!
震驚,后端根本沒授權,那要登錄做什么?是不是每個應用都這樣的?
然后我又換到另一個應用測試:
經測試,另一個應用需要帶授權字段,且這個字段是 blade-auth,其他的 Authorization/Cookie 都可以不要,這次我就簡單上個圖。
另外,假設刪除 Cookie,那么會影響下次 token 自動獲取嗎?會影響 token 自動更新邏輯嗎?這又得進行一波代碼邏輯分析……
根據 RefreshTokenKey 這個關鍵字,表明框架應該使用了 jwt 授權邏輯的 過期標志獲取新 token
的方案,但搜索發現此方案並未落實,然后實現有可能變成在 API 調用后 token 自動續期,或者到期后用戶需要重新登錄。
但是刪除 Cookie 后肯定是影響刷新頁面后的已有 token 獲取的,所以這時候要把存 Cookie 這個邏輯變為存 lcoalStore,這樣存就不會帶上無關 Cookie 了。
假設去除 Cookie ,會影響未來的功能嗎?
那肯定是會的,如果將來某個接口需要 Cookie, 還得專門針對這個接口做邏輯編寫不說,這個接口還是會出現帶上其他端口信息的問題。
假設通過域名隔離的方案,是否造成新的問題
對於此方案,可以不修改前端任何代碼,且可以使用 cookie 參數指定隔離情況。僅把部署方式部署到不同的域名(例如使用子域名區分應用,而不是使用端口區分應用)即可解決問題。
前端不用修改的原因是:當前的 Cookie 本身就當授權信息存儲使用,當更改部署方式之后,只是存儲的鍵不一樣,根據前端當前的邏輯照樣可以正常讀寫。
理論上后端代碼也不需要修改。
不過,修改之后需要發布新的可用鏈接,即需要告知使用的人員新的地址,造成一點溝通成本,如果要避免這個溝通成本也是可以的,對原來的地址做一個重定向即可。
總結
方案一:把 token 存在 store 中,自定義管理 token 銷毀邏輯。
去除 Cookie 攜帶(建議后端明確給出授權字段)。
方案二:使用子域名方式部署應用。
經討論預選:方案二。