国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

vue的token刷新處理的方法

2019-11-19 13:28:33
字體:
來源:轉載
供稿:網友

第一次接觸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}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 武鸣县| 昭苏县| 临邑县| 泾阳县| 浪卡子县| 巴青县| 垦利县| 金坛市| 江北区| 兴隆县| 三门峡市| 鄂尔多斯市| 鹤山市| 杂多县| 肇源县| 类乌齐县| 阿图什市| 东乌| 忻城县| 遂平县| 台北市| 固镇县| 高台县| 广德县| 贞丰县| 武安市| 栾川县| 涞水县| 平顺县| 佛坪县| 兰西县| 青浦区| 原平市| 交口县| 太原市| 桦川县| 杨浦区| 常德市| 青神县| 民勤县| 林州市|