vue的token刷新處理的方法
第一次接觸token處理,初來(lái)乍到,說(shuō)錯(cuò)的地方還請(qǐng)各位多多指教。
token身份驗(yàn)證機(jī)制
客戶端登錄請(qǐng)求成功后,服務(wù)器將用戶信息(如用戶id)使用特殊算法加密后作為驗(yàn)證的標(biāo)志發(fā)送給用戶(即token),當(dāng)用戶下次發(fā)起請(qǐng)求時(shí),會(huì)將這個(gè)token捎帶過(guò)來(lái),服務(wù)器再將這個(gè)token通過(guò)解密后進(jìn)行驗(yàn)證,通過(guò)的話,則向客戶端返回請(qǐng)求的數(shù)據(jù);反之,則請(qǐng)求失敗。
token優(yōu)點(diǎn)
它是無(wú)狀態(tài)的,且服務(wù)器不用像傳統(tǒng)的身份認(rèn)證(session)那樣需要保存會(huì)話信息,減輕了服務(wù)器的壓力。
vue的token刷新處理
在對(duì)token身份驗(yàn)證機(jī)制進(jìn)行一次簡(jiǎn)單介紹后,進(jìn)入正文...
一般為了安全性,token都會(huì)設(shè)置一個(gè)過(guò)期時(shí)間,在過(guò)期之后就無(wú)法請(qǐng)求相關(guān)接口了,這時(shí)應(yīng)該怎么辦呢,是直接退出登錄嗎?
在目前公司的項(xiàng)目里,為了更好的用戶體驗(yàn),我們選擇手動(dòng)刷新token。登錄請(qǐng)求成功后,會(huì)返回一個(gè)token和token過(guò)期時(shí)間,在每次請(qǐng)求api時(shí),前端可以先判斷一下token是否即將過(guò)期或已過(guò)期,如果是,則請(qǐng)求刷新token的接口,成功替換原來(lái)的token之后才可以重新發(fā)起請(qǐng)求。
下面,我們直接看代碼,這是在vue的請(qǐng)求攔截器里進(jìn)行的相關(guān)操作:
/*是否有請(qǐng)求正在刷新token*/ window.isRefreshing = false /*被掛起的請(qǐng)求數(shù)組*/ let refreshSubscribers = [] /*獲取刷新token請(qǐng)求的token*/ function getRefreshToken () { return JSON.parse(localStorage.auth).refresh_token } /*push所有請(qǐng)求到數(shù)組中*/ function subscribeTokenRefresh (cb) { refreshSubscribers.push(cb) } /*刷新請(qǐng)求(refreshSubscribers數(shù)組中的請(qǐng)求得到新的token之后會(huì)自執(zhí)行,用新的token去請(qǐng)求數(shù)據(jù))*/ function onRrefreshed (token) { refreshSubscribers.map(cb => cb(token)) } /*請(qǐng)求攔截器*/ ajax.interceptors.request.use( config => { const authTmp = localStorage.auth /*判斷是否已登錄*/ if (authTmp) { /*解析登錄信息*/ let auth = JSON.parse(authTmp) /*判斷auth是否存在*/ if (auth) { /*在請(qǐng)求頭中添加token類型、token*/ config.headers.Authorization = auth.token_type + ' ' + auth.token /*判斷刷新token請(qǐng)求的refresh_token是否過(guò)期*/ if (util.isRefreshTokenExpired()) { alert('刷新token過(guò)期,請(qǐng)重新登錄') /*清除本地保存的auth*/ localStorage.removeItem('auth') window.location.href = '#/login' return } /*判斷token是否將要過(guò)期*/ if (util.isTokenExpired() && config.url.indexOf('admin/auth/current') === -1) { /*判斷是否正在刷新*/ if (!window.isRefreshing) { /*將刷新token的標(biāo)志置為true*/ window.isRefreshing = true /*發(fā)起刷新token的請(qǐng)求*/ 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ā)起被掛起的請(qǐng)求*/ onRrefreshed(res.data.data.token) /*執(zhí)行onRefreshed函數(shù)后清空數(shù)組中保存的請(qǐng)求*/ refreshSubscribers = [] }).catch(err => { alert(err.response.data.message) /*清除本地保存的auth*/ // localStorage.removeItem('auth') window.location.href = '#/login' }) } /*把請(qǐng)求(token)=>{....}都push到一個(gè)數(shù)組中*/ let retry = new Promise((resolve, reject) => { /*(token) => {...}這個(gè)函數(shù)就是回調(diào)函數(shù)*/ subscribeTokenRefresh((token) => { config.headers.Authorization = 'Bearer ' + token /*將請(qǐng)求掛起*/ resolve(config) }) }) return retry } } return config } else { /*未登錄直接返回配置信息*/ return config } }, /*錯(cuò)誤操作*/ err => { return Promise.reject(err) } )
這里需要注意幾點(diǎn):
1、當(dāng)token即將過(guò)期或者已過(guò)期時(shí),原則上,我們只需要有一個(gè)接口去觸發(fā)刷新token的請(qǐng)求即可,這里的isRefreshing 變量,就起到這樣一個(gè)監(jiān)控的作用,它相當(dāng)于一把鎖,當(dāng)刷新token的操作被觸發(fā)后,其他的觸發(fā)操作就被排斥在外了。
window.isRefreshing = false
2、刷新token的接口,用到了一個(gè)另外的token(refresh_token),這也是出于安全性考慮的,并且它也有過(guò)期時(shí)間,不過(guò)這個(gè)過(guò)期時(shí)間一般都比普通token的過(guò)期時(shí)間要長(zhǎng),所以在上面代碼中,會(huì)發(fā)現(xiàn),我在請(qǐng)求攔截中優(yōu)先判斷了refresh_token是否過(guò)期,如果過(guò)期則直接退出登錄,不再進(jìn)行下一步的操作。
/*判斷刷新token請(qǐng)求的refresh_token是否過(guò)期*/ if (util.isRefreshTokenExpired() && config.url.indexOf('admin/auth/current') === -1) { alert('刷新token過(guò)期,請(qǐng)重新登錄') /*清除本地保存的auth*/ localStorage.removeItem('auth') window.location.href = '#/login' return }
3、在觸發(fā)了刷新token的操作后,我們還需要先將其他的請(qǐng)求掛起,在獲取新的token之后再重新發(fā)起這些請(qǐng)求。
/*把請(qǐng)求(token)=>{....}都push到一個(gè)數(shù)組中*/ let retry = new Promise((resolve, reject) => { /*(token) => {...}這個(gè)函數(shù)就是回調(diào)函數(shù)*/ subscribeTokenRefresh((token) => { config.headers.Authorization = 'Bearer ' + token /*將請(qǐng)求掛起*/ resolve(config) }) }) return retry
在刷新token請(qǐng)求的成功回調(diào)里執(zhí)行下面代碼,重新發(fā)起請(qǐng)求。
/*執(zhí)行數(shù)組里的函數(shù),重新發(fā)起被掛起的請(qǐng)求*/ onRrefreshed(res.data.data.token)
4、因?yàn)橛腥嗽谠u(píng)論里問(wèn)util文件,應(yīng)該是想知道具體怎么判斷token過(guò)期的,其實(shí)在獲得token時(shí),是有返回一個(gè)token過(guò)期時(shí)間 ,你可以先將它先保存起來(lái),然后在需要時(shí),拿出來(lái)與本地時(shí)間比較即可
/*判斷token是否過(guò)期*/ function isTokenExpired() { /*從localStorage中取出token過(guò)期時(shí)間*/ let expiredTime = new Date(JSON.parse(localStorage.auth).expired_at).getTime() / 1000 /*獲取本地時(shí)間*/ let nowTime = new Date().getTime() / 1000 /*獲取校驗(yàn)時(shí)間差*/ let diffTime = JSON.parse(sessionStorage.diffTime) /*校驗(yàn)本地時(shí)間*/ nowTime -= diffTime /*如果 < 10分鐘,則說(shuō)明即將過(guò)期*/ return (expiredTime - nowTime) < 10*60 }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- vue中雙token和無(wú)感刷新token的區(qū)別
- Vue實(shí)現(xiàn)雙token無(wú)感刷新的示例代碼
- vue2實(shí)現(xiàn)無(wú)感刷新token的方式詳解
- VUE前端實(shí)現(xiàn)token的無(wú)感刷新方式
- vuex刷新頁(yè)面丟失登錄token信息的解決方案
- Vue項(xiàng)目實(shí)現(xiàn)token無(wú)感刷新的示例代碼
- 前端使用vue實(shí)現(xiàn)token無(wú)感刷新的三種方案解析
- Vue3+Vite使用雙token實(shí)現(xiàn)無(wú)感刷新
- 關(guān)于Vue 消除Token過(guò)期時(shí)刷新頁(yè)面的重復(fù)提示問(wèn)題
- Vue項(xiàng)目中實(shí)現(xiàn)無(wú)感Token刷新的示例
相關(guān)文章
淺析Proxy可以優(yōu)化vue的數(shù)據(jù)監(jiān)聽(tīng)機(jī)制問(wèn)題及實(shí)現(xiàn)思路
這篇文章主要介紹了淺析Proxy可以優(yōu)化vue的數(shù)據(jù)監(jiān)聽(tīng)機(jī)制問(wèn)題及實(shí)現(xiàn)思路,需要的朋友可以參考下2018-11-11寫一個(gè)移動(dòng)端慣性滑動(dòng)&回彈Vue導(dǎo)航欄組件 ly-tab
前一段時(shí)間小編寫一個(gè)移動(dòng)端慣性滑動(dòng)&回彈Vue導(dǎo)航欄組件 ly-tab,覺(jué)的非常實(shí)用,大家可能在做項(xiàng)目時(shí)會(huì)用到,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-03-03vue中關(guān)于template報(bào)錯(cuò)等問(wèn)題的解決
這篇文章主要介紹了vue中關(guān)于template報(bào)錯(cuò)等問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04vue中beforeRouteLeave實(shí)現(xiàn)頁(yè)面回退不刷新的示例代碼
這篇文章主要介紹了vue中beforeRouteLeave實(shí)現(xiàn)頁(yè)面回退不刷新的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11vue+animation實(shí)現(xiàn)翻頁(yè)動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了vue+animation實(shí)現(xiàn)翻頁(yè)動(dòng)畫(huà),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06關(guān)于vue?src路徑動(dòng)態(tài)拼接的小知識(shí)
這篇文章主要介紹了vue?src路徑動(dòng)態(tài)拼接的小知識(shí),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2022-04-04vue學(xué)習(xí)筆記之過(guò)濾器的基本使用方法實(shí)例分析
這篇文章主要介紹了vue學(xué)習(xí)筆記之過(guò)濾器的基本使用方法,結(jié)合實(shí)例形式分析了vue.js過(guò)濾器的基本功能、用法與操作注意事項(xiàng),需要的朋友可以參考下2020-02-02