js項(xiàng)目中前端如何實(shí)現(xiàn)無(wú)感刷新token
前一陣遇到了一個(gè)問(wèn)題,線上平臺(tái)有時(shí)會(huì)出現(xiàn)用戶正在使用的時(shí)候,突然要用戶去進(jìn)行登錄,這樣會(huì)造成很不好的用戶體驗(yàn),但是當(dāng)時(shí)一直沒(méi)有好的思路因此擱置了下來(lái);通過(guò)零散時(shí)間查詢資料以及思考,最終解決了這個(gè)問(wèn)題,接下來(lái)跟大家分享一下!
環(huán)境
- 請(qǐng)求采用的 Axios V1.3.2。
- 平臺(tái)的采用的
JWT(JSON Web Tokens)進(jìn)行用戶登錄鑒權(quán)。
(拓展:JWT 是一種認(rèn)證機(jī)制,讓后臺(tái)知道該請(qǐng)求是來(lái)自于受信的客戶端;更詳細(xì)的可以自行查詢相關(guān)資料)
問(wèn)題現(xiàn)象
線上用戶在使用的時(shí)候,偶爾會(huì)出現(xiàn)突然跳轉(zhuǎn)到登錄頁(yè)面,需要重新登錄的現(xiàn)象。
原因
- 突然跳轉(zhuǎn)到登錄頁(yè)面,是由于當(dāng)前的 token 過(guò)期,導(dǎo)致請(qǐng)求失??;在
axios的響應(yīng)攔截axiosInstance.interceptors.response.use中處理失敗請(qǐng)求返回的狀態(tài)碼 401,此時(shí)得知token失效,因此跳轉(zhuǎn)到登錄頁(yè)面,讓用戶重新進(jìn)行登錄。 - 平臺(tái)目前的邏輯是在
token未過(guò)期內(nèi),用戶登錄平臺(tái)可直接進(jìn)入首頁(yè),無(wú)需進(jìn)行登錄操作;因此就存在該現(xiàn)象:用戶打開(kāi)平臺(tái),由于此時(shí)token未過(guò)期,用戶直接進(jìn)入到了首頁(yè),進(jìn)行其他操作。但是在用戶操作的過(guò)程中,token突然失效了,此時(shí)就會(huì)出現(xiàn)突然跳轉(zhuǎn)到登錄頁(yè)面,嚴(yán)重影響用戶的體驗(yàn)感!
(注:目前線上項(xiàng)目中存在數(shù)據(jù)大屏,一些實(shí)時(shí)數(shù)據(jù)的顯示;因此存在用戶長(zhǎng)時(shí)間停留在大屏頁(yè)面,不進(jìn)行操作,查看實(shí)時(shí)數(shù)據(jù)的情況)
切入點(diǎn)
- 怎樣及時(shí)的、在用戶感知不到的情況下更新
token? - 當(dāng)
token失效的情況下,出錯(cuò)的請(qǐng)求可能不僅只有一個(gè);當(dāng)失效的token更新后,怎樣將多個(gè)失敗的請(qǐng)求,重新發(fā)送?
操作流程
好了!經(jīng)過(guò)了一番分析后,我們找到了問(wèn)題的所在,并且確定了切入點(diǎn);那么接下來(lái)讓我們實(shí)操,將問(wèn)題解決掉。
前要:
1、我們僅從前端的角度去處理。
2、后端提供了兩個(gè)重要的參數(shù):accessToken(用于請(qǐng)求頭中,進(jìn)行鑒權(quán),存在有效期);refreshToken(刷新令牌,用于更新過(guò)期的 accessToken,相對(duì)于 accessToken 而言,它的有效期更長(zhǎng))。
1、處理 axios 響應(yīng)攔截
注:在我實(shí)際的項(xiàng)目中,accessToken 過(guò)期后端返回的 statusCode 值為 401,需要在axiosInstance.interceptors.response.use 的 error回調(diào)中進(jìn)行邏輯處理。
// 響應(yīng)攔截
axiosInstance.interceptors.response.use(
(response) => {
return response;
},
(error) => {
let {
data, config
} = error.response;
return new Promise((resolve, reject) => {
/**
* 判斷當(dāng)前請(qǐng)求失敗
* 是否由 toekn 失效導(dǎo)致的
*/
if (data.statusCode === 401) {
/**
* refreshToken 為封裝的有關(guān)更新 token 的相關(guān)操作
*/
refreshToken(() => {
resolve(axiosInstance(config));
});
} else {
reject(error.response);
}
})
}
)- 我們通過(guò)判斷
statusCode來(lái)確定,是否當(dāng)前請(qǐng)求失敗是由token過(guò)期導(dǎo)致的; - 使用 Promise 處理將失敗的請(qǐng)求,將由于
token過(guò)期導(dǎo)致的失敗請(qǐng)求存儲(chǔ)起來(lái)(存儲(chǔ)的是請(qǐng)求回調(diào)函數(shù),resolve 狀態(tài))。理由:后續(xù)我們更新了token后,可以將存儲(chǔ)的失敗請(qǐng)求重新發(fā)起,以此來(lái)達(dá)到用戶無(wú)感的體驗(yàn)
2、封裝 refreshToken 邏輯
要點(diǎn):
- 存儲(chǔ)由于
token過(guò)期導(dǎo)致的失敗的請(qǐng)求。 - 更新本地以及axios中頭部的
token。 - 當(dāng)
refreshToken刷新令牌也過(guò)期后,讓用戶重新登錄。
// 存儲(chǔ)由于 token 過(guò)期導(dǎo)致 失敗的請(qǐng)求
let expiredRequestArr: any[] = [];
/**
* 存儲(chǔ)當(dāng)前因?yàn)?token 失效導(dǎo)致發(fā)送失敗的請(qǐng)求
*/
const saveErrorRequest = (expiredRequest: () => any) => {
expiredRequestArr.push(expiredRequest);
}
// 避免頻繁發(fā)送更新
let firstRequre = true;
/**
* 利用 refreshToken 更新當(dāng)前使用的 token
*/
const updateTokenByRefreshToken = () => {
firstRequre = false;
axiosInstance.post(
'更新 token 的請(qǐng)求',
).then(res => {
let {
refreshToken, accessToken
} = res.data;
// 更新本地的token
localStorage.setItem('accessToken', accessToken);
// 更新請(qǐng)求頭中的 token
setAxiosHeader(accessToken);
localStorage.setItem('refreshToken', refreshToken);
/**
* 當(dāng)獲取了最新的 refreshToken, accessToken 后
* 重新發(fā)起之前失敗的請(qǐng)求
*/
expiredRequestArr.forEach(request => {
request();
})
expiredRequestArr = [];
}).catch(err => {
console.log('刷新 token 失敗err', err);
/**
* 此時(shí) refreshToken 也已經(jīng)失效了
* 返回登錄頁(yè),讓用戶重新進(jìn)行登錄操作
*/
window.location.href = `${HOME_PAGE}/login`;
})
}
/**
* 更新當(dāng)前已過(guò)期的 token
* @param expiredRequest 回調(diào)函數(shù),返回由token過(guò)期導(dǎo)致失敗的請(qǐng)求
*/
export const refreshToken = (expiredRequest: () => any) => {
saveErrorRequest(expiredRequest);
if (firstRequre) {
updateTokenByRefreshToken();
}
}總結(jié)
經(jīng)過(guò)一波分析以及操作,我們最終實(shí)現(xiàn)了實(shí)際項(xiàng)目中的無(wú)感刷新token,最主要的是有效避免了:用戶在平臺(tái)操作過(guò)程中突然要退出登錄的現(xiàn)象(尤其是當(dāng)用戶進(jìn)行信息填寫(xiě),突然要重新登錄,之前填寫(xiě)的信息全部作廢,是很容易讓人發(fā)狂的)。
到此這篇關(guān)于js項(xiàng)目中前端如何實(shí)現(xiàn)無(wú)感刷新token的文章就介紹到這了,更多相關(guān)js 無(wú)感刷新token內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js實(shí)現(xiàn)使用輸入input和改變change事件模擬手動(dòng)輸入
聚焦于JavaScript中的輸入模擬技術(shù),本指南將帶你探索如何使用input和change事件來(lái)創(chuàng)造逼真的手動(dòng)輸入效果,通過(guò)簡(jiǎn)單的代碼實(shí)現(xiàn),你將掌握這一實(shí)用的技巧,為你的Web應(yīng)用增添交互的樂(lè)趣,需要的朋友可以參考下2024-03-03
Bootstrap CSS組件之導(dǎo)航條(navbar)
這篇文章主要為大家詳細(xì)介紹了Bootstrap CSS組件之導(dǎo)航條(navbar),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
JavaScript鍵盤(pán)事件常見(jiàn)用法實(shí)例分析
這篇文章主要介紹了JavaScript鍵盤(pán)事件常見(jiàn)用法,簡(jiǎn)單描述了javascript鍵盤(pán)事件的分類、功能,并結(jié)合實(shí)例形式給出了javascript響應(yīng)鍵盤(pán)事件相關(guān)使用技巧,需要的朋友可以參考下2019-01-01
使用JavaScript動(dòng)態(tài)設(shè)置樣式實(shí)現(xiàn)代碼及演示動(dòng)畫(huà)
使用onmouseover和onmouseout事件實(shí)現(xiàn)不同的效果而且是使用js動(dòng)態(tài)實(shí)現(xiàn),本文有利于鞏固你js與css方面的知識(shí),感興趣的你可以了解下哦,希望本文對(duì)你有所幫助2013-01-01

