js項目中前端如何實現(xiàn)無感刷新token
前一陣遇到了一個問題,線上平臺有時會出現(xiàn)用戶正在使用的時候,突然要用戶去進行登錄,這樣會造成很不好的用戶體驗,但是當(dāng)時一直沒有好的思路因此擱置了下來;通過零散時間查詢資料以及思考,最終解決了這個問題,接下來跟大家分享一下!
環(huán)境
- 請求采用的 Axios V1.3.2。
- 平臺的采用的
JWT(JSON Web Tokens)
進行用戶登錄鑒權(quán)。
(拓展:JWT 是一種認證機制,讓后臺知道該請求是來自于受信的客戶端;更詳細的可以自行查詢相關(guān)資料)
問題現(xiàn)象
線上用戶在使用的時候,偶爾會出現(xiàn)突然跳轉(zhuǎn)到登錄頁面,需要重新登錄的現(xiàn)象。
原因
- 突然跳轉(zhuǎn)到登錄頁面,是由于當(dāng)前的 token 過期,導(dǎo)致請求失敗;在
axios
的響應(yīng)攔截axiosInstance.interceptors.response.use
中處理失敗請求返回的狀態(tài)碼 401,此時得知token
失效,因此跳轉(zhuǎn)到登錄頁面,讓用戶重新進行登錄。 - 平臺目前的邏輯是在
token
未過期內(nèi),用戶登錄平臺可直接進入首頁,無需進行登錄操作;因此就存在該現(xiàn)象:用戶打開平臺,由于此時token
未過期,用戶直接進入到了首頁,進行其他操作。但是在用戶操作的過程中,token
突然失效了,此時就會出現(xiàn)突然跳轉(zhuǎn)到登錄頁面,嚴(yán)重影響用戶的體驗感!
(注:目前線上項目中存在數(shù)據(jù)大屏,一些實時數(shù)據(jù)的顯示;因此存在用戶長時間停留在大屏頁面,不進行操作,查看實時數(shù)據(jù)的情況)
切入點
- 怎樣及時的、在用戶感知不到的情況下更新
token
? - 當(dāng)
token
失效的情況下,出錯的請求可能不僅只有一個;當(dāng)失效的token
更新后,怎樣將多個失敗的請求,重新發(fā)送?
操作流程
好了!經(jīng)過了一番分析后,我們找到了問題的所在,并且確定了切入點;那么接下來讓我們實操,將問題解決掉。
前要:
1、我們僅從前端的角度去處理。
2、后端提供了兩個重要的參數(shù):accessToken
(用于請求頭中,進行鑒權(quán),存在有效期);refreshToken
(刷新令牌,用于更新過期的 accessToken,相對于 accessToken 而言,它的有效期更長)。
1、處理 axios 響應(yīng)攔截
注:在我實際的項目中,accessToken
過期后端返回的 statusCode
值為 401,需要在axiosInstance.interceptors.response.use
的 error
回調(diào)中進行邏輯處理。
// 響應(yīng)攔截 axiosInstance.interceptors.response.use( (response) => { return response; }, (error) => { let { data, config } = error.response; return new Promise((resolve, reject) => { /** * 判斷當(dāng)前請求失敗 * 是否由 toekn 失效導(dǎo)致的 */ if (data.statusCode === 401) { /** * refreshToken 為封裝的有關(guān)更新 token 的相關(guān)操作 */ refreshToken(() => { resolve(axiosInstance(config)); }); } else { reject(error.response); } }) } )
- 我們通過判斷
statusCode
來確定,是否當(dāng)前請求失敗是由token
過期導(dǎo)致的; - 使用 Promise 處理將失敗的請求,將由于
token
過期導(dǎo)致的失敗請求存儲起來(存儲的是請求回調(diào)函數(shù),resolve 狀態(tài))。理由:后續(xù)我們更新了token
后,可以將存儲的失敗請求重新發(fā)起,以此來達到用戶無感的體驗
2、封裝 refreshToken 邏輯
要點:
- 存儲由于
token
過期導(dǎo)致的失敗的請求。 - 更新本地以及axios中頭部的
token
。 - 當(dāng)
refreshToken
刷新令牌也過期后,讓用戶重新登錄。
// 存儲由于 token 過期導(dǎo)致 失敗的請求 let expiredRequestArr: any[] = []; /** * 存儲當(dāng)前因為 token 失效導(dǎo)致發(fā)送失敗的請求 */ const saveErrorRequest = (expiredRequest: () => any) => { expiredRequestArr.push(expiredRequest); } // 避免頻繁發(fā)送更新 let firstRequre = true; /** * 利用 refreshToken 更新當(dāng)前使用的 token */ const updateTokenByRefreshToken = () => { firstRequre = false; axiosInstance.post( '更新 token 的請求', ).then(res => { let { refreshToken, accessToken } = res.data; // 更新本地的token localStorage.setItem('accessToken', accessToken); // 更新請求頭中的 token setAxiosHeader(accessToken); localStorage.setItem('refreshToken', refreshToken); /** * 當(dāng)獲取了最新的 refreshToken, accessToken 后 * 重新發(fā)起之前失敗的請求 */ expiredRequestArr.forEach(request => { request(); }) expiredRequestArr = []; }).catch(err => { console.log('刷新 token 失敗err', err); /** * 此時 refreshToken 也已經(jīng)失效了 * 返回登錄頁,讓用戶重新進行登錄操作 */ window.location.href = `${HOME_PAGE}/login`; }) } /** * 更新當(dāng)前已過期的 token * @param expiredRequest 回調(diào)函數(shù),返回由token過期導(dǎo)致失敗的請求 */ export const refreshToken = (expiredRequest: () => any) => { saveErrorRequest(expiredRequest); if (firstRequre) { updateTokenByRefreshToken(); } }
總結(jié)
經(jīng)過一波分析以及操作,我們最終實現(xiàn)了實際項目中的無感刷新token
,最主要的是有效避免了:用戶在平臺操作過程中突然要退出登錄的現(xiàn)象(尤其是當(dāng)用戶進行信息填寫,突然要重新登錄,之前填寫的信息全部作廢,是很容易讓人發(fā)狂的)。
到此這篇關(guān)于js項目中前端如何實現(xiàn)無感刷新token的文章就介紹到這了,更多相關(guān)js 無感刷新token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實現(xiàn)字符串轉(zhuǎn)字符數(shù)組的兩種方式
在 JavaScript 的編程世界里,字符串和數(shù)組是極為常見的數(shù)據(jù)類型,在實際開發(fā)中,我們常常會遇到需要將字符串轉(zhuǎn)換為字符數(shù)組的情況,接下來,我們將深入探討如何使用 JavaScript 實現(xiàn)這一轉(zhuǎn)換,同時結(jié)合代碼示例詳細分析不同方法的特點,需要的朋友可以參考下2025-04-04學(xué)習(xí)JavaScript設(shè)計模式之裝飾者模式
這篇文章主要為大家介紹了JavaScript設(shè)計模式中的裝飾者模式,對JavaScript設(shè)計模式感興趣的小伙伴們可以參考一下2016-01-01layui使用form表單實現(xiàn)post請求頁面跳轉(zhuǎn)的方法
今天小編就為大家分享一篇layui使用form表單實現(xiàn)post請求頁面跳轉(zhuǎn)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09