【SSO單點登錄】JWT續簽問題 && OAuth2.0 中的refreshToken刷新機制

語言: CN / TW / HK

theme: smartblue highlight: solarized-light


持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第 5 天,點擊查看活動詳情

大家好,我是melo,一名大三後台練習生,不知不覺練習時間長達一年了!!!

👉本篇速覽

  • JWT續簽問題

    • 快過期時返回新的token
    • refreshToken

      • 如何判斷refreshToken的有效性
      • 擴展 -- OAuth2.0 中的refreshToken刷新機制
    • 其他需要刷新token的情況

      • 用户修改了角色權限
      • 刪除了某個身份角色

為什麼需要續簽

如果給JWT設定了一個有效時間的話,時間到JWT是會過期的。但假如這個時候用户正在提交重要信息,填了一大堆信息,按下按鈕時,後台攔截器發現token過期,告知前端,前端直接退回登錄頁,那這次提交就相當於無效了,還得登錄後重新填一遍【當然前端也能做緩存,這裏就不考慮那麼多了,只是個栗子】

而原始JWT設計下,是沒有考慮續簽問題的。所以續簽(即延長JWT的過期時間)工作需要我們自己來做。

快過期了返回新的token

類似於 Session 認證中的做法: 假設服務端給的 token 有效期設置為30分鐘,服務端每次進行校驗時,如果發現 token 的有效期馬上快過期了, 服務端就重新生成 token 給客户端。

客户端每次請求都檢查新舊token,如果不一致,則更新客户端存儲的token。 - 這種做法的問題是僅僅在快過期的時候請求才會更新 token ,對客户端不是很友好。

refreshToken刷新機制

流程圖

用户登錄返回兩個 token :第一個是 acessToken ,它的過期時間比較短,比如是1天;另外一個是 refreshToken 它的過期時間更長一點,可以是accessToken的2倍:2天。

客户端登錄後,將 accessToken和refreshToken 保存在客户端本地,每次訪問將 accessToken 傳給服務端。服務端校驗 accessToken 的有效性,

如果過期的話,就將 refreshToken 傳給服務端。如果 refreshToken 有效,服務端就生成新的 accessToken 給客户端。否則,客户端就重新登錄即可。

🎆如何判斷refreshToken的有效性

將生成的 Refresh Token 以及過期時間存儲在服務端的數據庫中,由於 Refresh Token 不會在客户端請求業務接口時驗證,只有在申請新的 Access Token 時才會驗證,所以將 Refresh Token 存儲在數據庫中,不會對業務接口的響應時間造成影響,也不需要像 Session 一樣一直保持在內存中以應對大量的請求。

當然,更安全的方式是,客户端需要綁定一個client_id和secret,服務端會驗證這個refreshToken是否是改客户端發起的,防止被盜用【這個是後話了,我們後續基於token的SSO單點登錄,驗證令牌ticket的時候還會着重講解】

缺點

  • 重新請求獲取 token 的過程中會有短暫 token 不可用的情況(可以通過在客户端設置定時器,當accessToken 快過期的時候,提前去通過 refreshToken 獲取新的accessToken)。

擴展 -- OAuth2.0中的刷新機制

客户端在獲得access token的同時也會在響應信息中得到一個名為expires_in的數據,它表示當前獲得的access token會在多少秒以後過期。 當超過該指定的秒數後,access token便會過期。當access token過期後,如果客户端依然用它訪問服務,服務端就會返回invalid_token的錯誤或401錯誤碼。 ```java HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store Pragma: no-cache

{ "error": "invaild_token" } ```

如果用户訪問的時候,客户端的"訪問令牌AccessToken"已經過期,則需要使用"更新令牌refreshToken"申請一個新的訪問令牌。

客户端發出更新令牌的HTTP請求,包含以下參數:

  • granttype:表示使用的授權模式,此處的值固定為"refreshtoken",必選項。
  • refresh_token:表示早前收到的更新令牌,必選項。
  • scope:表示申請的授權範圍,不可以超出上一次申請的範圍,如果省略該參數,則表示與上一次一致。

```java POST /v1/oauth2/token HTTP/1.1 Host: melo.com Authorization: Bearer zskldjflsdjflksjdflkjsd Content-Type: application/x-www-form-urlencoded

grent_type=refresh_token&refresh_tokne=ajsldkjflskdfjldfg ```

其他需要刷新token的情況

用户修改了角色的權限

由於權限是在登錄的時候,綁定在token裏邊了,若登錄後,管理員修改了角色的權限,而服務端此時還拿一開始登錄的token去獲取權限的話,就會出現不同步,所以需要主動刷新token更新權限

刪除了某個身份角色

情況跟上邊是類似的,本質上也是身份權限發生了變更,只要是token中的信息,發生了變化,而我們之後還要用到,會出現數據不一致的情況,就需要刷新token

💠下篇預告

  • 本篇就JWT續簽問題和OAuth2.0展開了解讀,也算是淺提及到了OAuth2.0機制,後續的SSO單點登錄基於ticket形式實現,其中就借鑑了OAuth2.0中的授權碼機制。
  • 聊完了前置知識,Cookie和Session以及JWT,下篇我們將正式進入SSO單點登錄篇,展開第一種SSO單點登錄方式--基於Cookie和Session實現,敬請期待~

🧿友鏈