vue的token刷新處理

第一次接觸token處理,初來乍到涛贯,說錯的地方還請各位多多指教。

token身份驗證機(jī)制

客戶端登錄請求成功后蔚出,服務(wù)器將用戶信息(如用戶id)使用特殊算法加密后作為驗證的標(biāo)志發(fā)送給用戶(即token)弟翘,當(dāng)用戶下次發(fā)起請求時,會將這個token捎帶過來骄酗,服務(wù)器再將這個token通過解密后進(jìn)行驗證稀余,通過的話,則向客戶端返回請求的數(shù)據(jù)趋翻;反之睛琳,則請求失敗。

token優(yōu)點

它是無狀態(tài)的踏烙,且服務(wù)器不用像傳統(tǒng)的身份認(rèn)證(session)那樣需要保存會話信息师骗,減輕了服務(wù)器的壓力。

vue的token刷新處理

在對token身份驗證機(jī)制進(jìn)行一次簡單介紹后讨惩,進(jìn)入正文...
一般為了安全性辟癌,token都會設(shè)置一個過期時間,在過期之后就無法請求相關(guān)接口了荐捻,這時應(yīng)該怎么辦呢黍少,是直接退出登錄嗎?
在目前公司的項目里处面,為了更好的用戶體驗厂置,我們選擇手動刷新token。登錄請求成功后魂角,會返回一個token和token過期時間昵济,在每次請求api時,前端可以先判斷一下token是否即將過期或已過期,如果是砸紊,則請求刷新token的接口传于,成功替換原來的token之后才可以重新發(fā)起請求。
下面醉顽,我們直接看代碼沼溜,這是在vue的請求攔截器里進(jìn)行的相關(guān)操作:

/*是否有請求正在刷新token*/
window.isRefreshing = false
/*被掛起的請求數(shù)組*/
let refreshSubscribers = []

/*獲取刷新token請求的token*/
function getRefreshToken () {
  return JSON.parse(localStorage.auth).refresh_token
}

/*push所有請求到數(shù)組中*/
function subscribeTokenRefresh (cb) {
  refreshSubscribers.push(cb)
}

/*刷新請求(refreshSubscribers數(shù)組中的請求得到新的token之后會自執(zhí)行,用新的token去請求數(shù)據(jù))*/
function onRrefreshed (token) {
  refreshSubscribers.map(cb => cb(token))
}

/*請求攔截器*/
ajax.interceptors.request.use(
  config => {
    const authTmp = localStorage.auth
    /*判斷是否已登錄*/
    if (authTmp) {
      /*解析登錄信息*/
      let auth = JSON.parse(authTmp)
      /*判斷auth是否存在*/
      if (auth) {
        /*在請求頭中添加token類型游添、token*/
        config.headers.Authorization = auth.token_type + ' ' + auth.token
        /*判斷刷新token請求的refresh_token是否過期*/
        if (util.isRefreshTokenExpired()) {
          alert('刷新token過期系草,請重新登錄')
          /*清除本地保存的auth*/
          localStorage.removeItem('auth')
          window.location.href = '#/login'
          return
        }
        /*判斷token是否將要過期*/
        if (util.isTokenExpired() && config.url.indexOf('admin/auth/current') === -1) {
          /*判斷是否正在刷新*/
          if (!window.isRefreshing) {
            /*將刷新token的標(biāo)志置為true*/
            window.isRefreshing = true
            /*發(fā)起刷新token的請求*/
            apiList.refreshToken({refresh_token: getRefreshToken()}).then(res => {
              /*將標(biāo)志置為false*/
              window.isRefreshing = false
              /*成功刷新token*/
              config.headers.Authorization = res.data.data.token_type + ' ' + res.data.data.token
              /*更新auth*/
              localStorage.setItem('auth', JSON.stringify(res.data.data))
              /*執(zhí)行數(shù)組里的函數(shù),重新發(fā)起被掛起的請求*/
              onRrefreshed(res.data.data.token)
              /*執(zhí)行onRefreshed函數(shù)后清空數(shù)組中保存的請求*/
              refreshSubscribers = []
            }).catch(err => {
              alert(err.response.data.message)
              /*清除本地保存的auth*/
              // localStorage.removeItem('auth')
              window.location.href = '#/login'
            })
          }
          /*把請求(token)=>{....}都push到一個數(shù)組中*/
          let retry = new Promise((resolve, reject) => {
            /*(token) => {...}這個函數(shù)就是回調(diào)函數(shù)*/
            subscribeTokenRefresh((token) => {
              config.headers.Authorization = 'Bearer ' + token
              /*將請求掛起*/
              resolve(config)
            })
          })
          return retry
        }
      }
      return config

    } else {
      /*未登錄直接返回配置信息*/
      return config
    }
  },
  /*錯誤操作*/
  err => {
    return Promise.reject(err)
  }
)

這里需要注意幾點:
1、當(dāng)token即將過期或者已過期時唆涝,原則上找都,我們只需要有一個接口去觸發(fā)刷新token的請求即可,這里的isRefreshing 變量廊酣,就起到這樣一個監(jiān)控的作用能耻,它相當(dāng)于一把鎖,當(dāng)刷新token的操作被觸發(fā)后亡驰,其他的觸發(fā)操作就被排斥在外了晓猛。

window.isRefreshing = false

2、刷新token的接口凡辱,用到了一個另外的token(refresh_token)戒职,這也是出于安全性考慮的,并且它也有過期時間透乾,不過這個過期時間一般都比普通token的過期時間要長洪燥,所以在上面代碼中,會發(fā)現(xiàn)乳乌,我在請求攔截中優(yōu)先判斷了refresh_token是否過期捧韵,如果過期則直接退出登錄,不再進(jìn)行下一步的操作钦扭。

 /*判斷刷新token請求的refresh_token是否過期*/
if (util.isRefreshTokenExpired() && config.url.indexOf('admin/auth/current') === -1) {
  alert('刷新token過期纫版,請重新登錄')
  /*清除本地保存的auth*/
  localStorage.removeItem('auth')
  window.location.href = '#/login'
  return
}

3、在觸發(fā)了刷新token的操作后客情,我們還需要先將其他的請求掛起其弊,在獲取新的token之后再重新發(fā)起這些請求。

/*把請求(token)=>{....}都push到一個數(shù)組中*/
let retry = new Promise((resolve, reject) => {
  /*(token) => {...}這個函數(shù)就是回調(diào)函數(shù)*/
  subscribeTokenRefresh((token) => {
    config.headers.Authorization = 'Bearer ' + token
    /*將請求掛起*/
    resolve(config)
  })
})
return retry

在刷新token請求的成功回調(diào)里執(zhí)行下面代碼膀斋,重新發(fā)起請求梭伐。

 /*執(zhí)行數(shù)組里的函數(shù),重新發(fā)起被掛起的請求*/
 onRrefreshed(res.data.data.token)

4、因為有人在評論里問util文件仰担,應(yīng)該是想知道具體怎么判斷token過期的糊识,其實在獲得token時,是有返回一個token過期時間 ,你可以先將它先保存起來赂苗,然后在需要時愉耙,拿出來與本地時間比較即可

/*判斷token是否過期*/
function isTokenExpired() {
  /*從localStorage中取出token過期時間*/
  let expiredTime = new Date(JSON.parse(localStorage.auth).expired_at).getTime() / 1000
  /*獲取本地時間*/
  let nowTime = new Date().getTime() / 1000
  /*獲取校驗時間差*/
  let diffTime = JSON.parse(sessionStorage.diffTime)
  /*校驗本地時間*/
  nowTime -= diffTime
  /*如果 < 10分鐘,則說明即將過期*/
  return (expiredTime - nowTime) < 10*60
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拌滋,一起剝皮案震驚了整個濱河市朴沿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌败砂,老刑警劉巖赌渣,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異昌犹,居然都是意外死亡坚芜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門斜姥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸿竖,“玉大人,你說我怎么就攤上這事疾渴∏Ч幔” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵搞坝,是天一觀的道長。 經(jīng)常有香客問我魁袜,道長桩撮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任峰弹,我火速辦了婚禮店量,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鞠呈。我一直安慰自己融师,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布蚁吝。 她就那樣靜靜地躺著旱爆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪窘茁。 梳的紋絲不亂的頭發(fā)上怀伦,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機(jī)與錄音山林,去河邊找鬼房待。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桑孩。 我是一名探鬼主播拜鹤,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼流椒!你這毒婦竟也來了敏簿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤镣隶,失蹤者是張志新(化名)和其女友劉穎极谊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體安岂,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡轻猖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了域那。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咙边。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖次员,靈堂內(nèi)的尸體忽然破棺而出败许,到底是詐尸還是另有隱情,我是刑警寧澤淑蔚,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布市殷,位于F島的核電站,受9級特大地震影響刹衫,放射性物質(zhì)發(fā)生泄漏醋寝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一带迟、第九天 我趴在偏房一處隱蔽的房頂上張望音羞。 院中可真熱鬧,春花似錦仓犬、人聲如沸嗅绰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窘面。三九已至,卻和暖如春律歼,著一層夾襖步出監(jiān)牢的瞬間民镜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工险毁, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留制圈,地道東北人们童。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像鲸鹦,于是被迫代替她去往敵國和親慧库。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容