OAuth2.0刷新Token,正在操作時,Token不過期

文件名稱 版本號 作者 qq 版本
OAuth2.0刷新Token v1.0.0 學生宮布 8416837 SpringBoot 2.2.6
SpringCloud Hoxton.SR4

需求

  • 保證頁面不會在正在操作中卻彈出Token過期,這樣體驗不好。除非好久(設定的閾值)沒有操作頁面了,顯示已過期才合理。

假設你已經搭建好OAuth2.0服務器

  • 登錄(授權)成功後,響應數據長這個樣子: 在這裏插入圖片描述
名詞 釋義 備註
access_token 作爲消費服務的通行證,逾期會失效
refresh_token 用來換取新的access_token,會失效,但一般應該設置比access_token晚些失效
expires_in 多久過期(秒) 可在數據庫設置或者在令牌管理器代碼設置
  • 但如果正在操作中,令牌(通行證)突然到期失效了,那多尷尬
  • 因此需要在即將過期或已經過期的時候,刷新Token。——前提是refresh_token沒有過期且合法。

解決辦法

  • 前提:可以成功獲取Token,併成功在客戶端維護Token、過期時間

1)定時器

  • 原理 計算Token過期的時間點,開始計時,噹噹前時間點接近過期點的時候,執行刷新Token操作。要保證每個頁面都可能觸發計時器,且只能有一個,當頁面刷新時,計時器不受影響。
  • 代碼 節選
// 從存儲獲取過期時間
computed: mapGetters(['userInfo', 'isLock', 'isCollapse', 'website', 'expires_in']),
... ...
// 這裏是aJax請求攔截器
// 如果即將過期,則調用刷新API,參數是refresh_token, grant_type:授權類型,即refresh_token, scope;並鎖住刷新接口
          if (this.expires_in <= 1000 && !this.refreshLock) {
            this.refreshLock = true
            this.$store
              .dispatch('RefreshToken')
              .catch(() => {
                clearInterval(this.refreshTime)
              });
              
            this.refreshLock = false
          }
          // expires_in遞減
          this.$store.commit("SET_EXPIRES_IN", this.expires_in - 10);
... ...

this.$store.dispatch('RefreshToken'):調用刷新 API

2)請求攔截式,每次請求權限接口都判斷是否可以刷新Token了

  • 代碼 節選
// 這裏是aJax請求攔截器
window.isRefreshing = false
... ...
 // futureTime:Token在將來某個時間點過期
  if (!window.isRefreshing && futureTime && (futureTime - new Date().getTime() ) <= EXPIRED_IN_THIS_SECONDS ) { // 如果expires_in_time eq 0,則很可能是初次登陸,從而勿須刷新令牌 假如設置還差6秒過期
    // 鎖 避免多個調用重複刷新
    window.isRefreshing = true
    // 刷新Token

如果同時調用多個接口,而此時Token已經過期,但refresh_token沒有過期的話,最先刷新的接口可以執行成功,另外的接口不會刷新,會導致請求失敗。但是之後會正常,因爲已經刷新了。見下圖:

Mon 06Mon 13請求1刷新中 請求路上 請求3請求中,但是木有Token 請求2時序圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章