首頁  >  文章  >  web前端  >  vue中token如何進行刷新處理

vue中token如何進行刷新處理

不言
不言原創
2018-07-21 11:57:373027瀏覽

這篇文章跟大家分享的是關於vue中token如何進行刷新處理,內容很不錯,有需要的朋友可以參考一下,希望可以幫助到大家。

token身份驗證機制

客戶端登入要求成功後,伺服器將用戶資訊(如用戶id)使用特殊演算法加密後作為驗證的標誌傳送給用戶(即token),當用戶下次發起請求時,會將這個token捎帶過來,伺服器再將這個token通過解密後進行驗證,通過的話,則向客戶端返回請求的資料;反之,則請求失敗。

token優點

它是無狀態的,且伺服器不用像傳統的身份認證(session)那樣需要保存會話信息,減輕了伺服器的壓力。

vue的token刷新處理

在對token身份驗證機制進行一次簡單介紹後,進入正文...

一般為了安全性,token都會設定一個過期時間,在過期之後就無法請求相關介面了,這時該怎麼辦呢,是直接退出登入嗎?

在目前公司的專案裡,為了更好的使用者體驗,我們選擇手動刷新token。登入請求成功後,會返回一個token和token過期時間,在每次請求api時,前端可以先判斷一下token是否即將過期或已過期,如果是,則請求刷新token的接口,成功替換原來的token之後才可以重新發起請求。

下面,我們直接看程式碼,這是在vue的請求攔截器裡進行的相關操作:

/*是否有请求正在刷新token*/
window.isRefreshing = false
/*被挂起的请求数组*/
let refreshSubscribers = []

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

/*push所有请求到数组中*/
function subscribeTokenRefresh (cb) {
 refreshSubscribers.push(cb)
}

/*刷新请求(refreshSubscribers数组中的请求得到新的token之后会自执行,用新的token去请求数据)*/
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的标志置为true*/
      window.isRefreshing = true
      /*发起刷新token的请求*/
      apiList.refreshToken({refresh_token: getRefreshToken()}).then(res => {
       /*将标志置为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))
       /*执行数组里的函数,重新发起被挂起的请求*/
       onRrefreshed(res.data.data.token)
       /*执行onRefreshed函数后清空数组中保存的请求*/
       refreshSubscribers = []
      }).catch(err => {
       alert(err.response.data.message)
       /*清除本地保存的auth*/
       // localStorage.removeItem('auth')
       window.location.href = '#/login'
      })
     }
     /*把请求(token)=>{....}都push到一个数组中*/
     let retry = new Promise((resolve, reject) => {
      /*(token) => {...}这个函数就是回调函数*/
      subscribeTokenRefresh((token) => {
       config.headers.Authorization = 'Bearer ' + token
       /*将请求挂起*/
       resolve(config)
      })
     })
     return retry
    }
   }
   return config

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

這裡需要注意幾點:

1、當token即將過期或已過期時,原則上,我們只需要有一個接口去觸發刷新token的請求即可,這裡的isRefreshing 變量,就起到這樣一個監控的作用,它相當於一把鎖,當刷新token的操作被觸發後,其他的觸發操作就被排斥在外了。

window.isRefreshing = false

2、刷新token的接口,用到了一個另外的token(refresh_token),這也是出於安全性考慮的,並且它也有過期時間,不過這個過期時間一般都比普通token的過期時間要長,所以在上面程式碼中,會發現,我在請求攔截中優先判斷了refresh_token是否過期,如果過期則直接退出登錄,不再進行下一步的操作。

 /*判断刷新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、在觸發了刷新token的操作後,我們還需要先將其他的請求掛起,在取得新的token之後再重新發起這些請求。

/*把请求(token)=>{....}都push到一个数组中*/
let retry = new Promise((resolve, reject) => {
 /*(token) => {...}这个函数就是回调函数*/
 subscribeTokenRefresh((token) => {
  config.headers.Authorization = 'Bearer ' + token
  /*将请求挂起*/
  resolve(config)
 })
})
return retry

在刷新token請求的成功回呼裡執行下面程式碼,重新發起請求。

 /*执行数组里的函数,重新发起被挂起的请求*/
 onRrefreshed(res.data.data.token)

4、因為有人在評論裡問util文件,應該是想知道具體怎麼判斷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
}

相關推薦:

Vue中SFC和vue-loader的具體分析

vue父子元件之間是如何進行傳值的

以上是vue中token如何進行刷新處理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn