前端登錄token失效實現(xiàn)雙Token無感刷新詳細步驟
一、方案背景
在用戶登錄系統(tǒng)后,為了保障安全性和用戶體驗,通常采用Token機制進行身份驗證。然而,單一的 Token 存在過期問題,導(dǎo)致用戶需要頻繁重新登錄,影響使用體驗。為解決這一問題,本方案提出采用雙Token機制實現(xiàn)前端登錄不掉線的無感刷新。
二、方案目標
- 實現(xiàn)用戶登錄后,在
Token過期前自動刷新,避免用戶頻繁重新登錄。 - 確保刷新過程對用戶無感知,不影響用戶正常操作。
- 保障系統(tǒng)的安全性,防止非法訪問。
三、技術(shù)原理
3.1. 雙 Token 機制
Access Token:用于用戶身份驗證,設(shè)置較短的過期時間(如 30 分鐘)。在每次請求時,前端將Access Token添加到請求頭中,服務(wù)器驗證其有效性后返回請求結(jié)果。Refresh Token:用于獲取新的Access Token,設(shè)置較長的過期時間(如 7 天)。當(dāng)Access Token過期時,前端使用Refresh Token向服務(wù)器請求新的Access Token。
3.2. 無感刷新流程
- 前端在發(fā)送請求時,先檢查
Access Token是否過期。如果未過期,正常發(fā)送請求。 - 如果
Access Token過期,前端攔截該請求,并使用Refresh Token發(fā)起刷新請求。 - 服務(wù)器驗證
Refresh Token的有效性,如果有效,返回新的Access Token和Refresh Token。 - 前端保存新的
Access Token和Refresh Token,并重新發(fā)送之前被攔截的請求。
四、具體實現(xiàn)步驟
4.1. 登錄流程
- 用戶輸入用戶名和密碼進行登錄,前端將登錄信息發(fā)送給服務(wù)器。
- 服務(wù)器驗證登錄信息成功后,生成
Access Token和Refresh Token,并將其返回給前端。 - 前端將
Access Token和Refresh Token保存到本地存儲(如LocalStorage)中。
4.2. 請求攔截
- 使用前端框架的攔截器(如
Vue的axios攔截器)攔截所有請求。 - 在請求發(fā)送前,從本地存儲中獲取
Access Token,并將其添加到請求頭中。
axios.interceptors.request.use((config) => {
const access_token = localStorage.getItem("access_token");
if (access_token) {
config.headers.Authorization = `Bearer ${access_token}`;
}
return config;
});
4.3. 響應(yīng)攔截與刷新
- 攔截服務(wù)器返回的響應(yīng),檢查響應(yīng)狀態(tài)碼。如果狀態(tài)碼為
401(表示Access Token過期),則執(zhí)行刷新操作。 - 設(shè)置一個標志位
isRefreshing,防止多個請求同時觸發(fā)刷新流程。當(dāng)isRefreshing為true時,后續(xù)請求將被暫存到一個隊列中,等待刷新完成后再重新發(fā)送。 - 使用
Refresh Token發(fā)起刷新請求,請求新的Access Token和Refresh Token。 - 在刷新請求成功后,更新本地存儲中的
Access Token和Refresh Token,并將標志位isRefreshing設(shè)置為false。 - 遍歷請求隊列,重新發(fā)送之前被攔截的請求。
axios.interceptors.response.use(
(response) => {
return response;
},
async (error) => {
const { data, status, config } = error.response;
if (status === 401 && config.url !== "/refresh") {
const isRefreshing = false;
if (!isRefreshing) {
isRefreshing = true;
try {
const res = await api.get("/refresh", {
params: {
token: localStorage.getItem("refresh_token"),
},
});
localStorage.setItem("access_token", res.data.access_token);
localStorage.setItem("refresh_token", res.data.refresh_token);
isRefreshing = false;
// 重新發(fā)送之前被攔截的請求
return api(config);
} catch (err) {
// 刷新失敗,跳轉(zhuǎn)到登錄頁面
window.location.href = "/login";
}
} else {
// 將請求添加到隊列中,等待刷新完成后再重新發(fā)送
requests.push(() => api(config));
}
}
return Promise.reject(error);
}
);
4.4. 錯誤處理:
- 如果刷新請求失敗(如
Refresh Token過期或無效),則跳轉(zhuǎn)到登錄頁面,提示用戶重新登錄。 - 對于其他類型的錯誤,根據(jù)具體情況進行相應(yīng)的處理,如顯示錯誤信息等。
五、安全性考慮
- HTTPS 協(xié)議:確保所有通信都通過 HTTPS 協(xié)議進行,防止
Token在傳輸過程中被竊取。 - 設(shè)置合理的過期時間:根據(jù)系統(tǒng)的安全要求和用戶體驗,合理設(shè)置
Access Token和Refresh Token的過期時間。Access Token過期時間較短,減少被濫用的風(fēng)險;Refresh Token過期時間較長,但也要定期更換,增加安全性。 - 防止
Refresh Token泄露:對Refresh Token進行嚴格的保護,避免泄露。例如,不要在URL中傳遞Refresh Token,只在請求頭中傳遞。 - 限制刷新次數(shù):可以設(shè)置
Refresh Token的刷新次數(shù)限制,防止被惡意刷新。
六、性能優(yōu)化
- 減少刷新頻率:通過合理設(shè)置
Access Token的過期時間,盡量減少刷新操作的頻率。 - 緩存機制:對于一些不經(jīng)常變化的數(shù)據(jù),可以使用緩存機制,減少請求次數(shù),提高系統(tǒng)性能。
- 合并請求:在可能的情況下,將多個請求合并為一個請求,減少網(wǎng)絡(luò)請求的次數(shù)。
七、總結(jié)
本方案通過采用雙 Token 機制,實現(xiàn)了前端登錄不掉線的無感刷新。在保障系統(tǒng)安全性的前提下,提高了用戶體驗,減少了用戶頻繁重新登錄的麻煩。同時,通過合理的安全性考慮和性能優(yōu)化措施,確保系統(tǒng)的穩(wěn)定性和高效性。在實際應(yīng)用中,可以根據(jù)具體業(yè)務(wù)需求進行適當(dāng)?shù)恼{(diào)整和優(yōu)化。
到此這篇關(guān)于前端登錄token失效實現(xiàn)雙Token無感刷新的文章就介紹到這了,更多相關(guān)前端雙Token無感刷新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實現(xiàn)字符串轉(zhuǎn)數(shù)組的6種方法總結(jié)
數(shù)組是?JavaScript?中最強大的數(shù)據(jù)結(jié)構(gòu),我們常常通過將字符串轉(zhuǎn)換為數(shù)組來解決許多算法。本文為大家總結(jié)了6個JS字符串轉(zhuǎn)數(shù)組的方法,希望對你有所幫助2022-09-09
基于Bootstrap下拉框插件bootstrap-select使用方法詳解
這篇文章主要為大家詳細介紹了基于Bootstrap下拉框插件bootstrap-select的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-08-08
JavaScrip調(diào)試技巧之?dāng)帱c調(diào)試
本篇文章給大家介紹javascript調(diào)試技巧之?dāng)帱c調(diào)試,主要介紹使用Firebug、debugger、debugger在程序中加入斷點調(diào)試等,但是這些調(diào)試技巧都不借助于瀏覽器之外的工具,其他瀏覽器主要是opera、safari、chrome和ie8,感興趣的小伙伴一起看看吧2015-10-10
JavaScript高級程序設(shè)計 閱讀筆記(十八) js跨平臺的事件
js跨平臺的事件經(jīng)驗分享,需要的朋友可以參考下2012-08-08
JavaScript實現(xiàn)私有屬性的幾種方式小結(jié)
在JavaScript中,私有屬性是指只能在對象內(nèi)部訪問的屬性,外部無法直接訪問,JavaScript并沒有提供官方的私有屬性的支持,但可以通過一些技巧來模擬實現(xiàn)私有屬性,所以本文給大家總結(jié)了JavaScript實現(xiàn)私有屬性的幾種方式,需要的朋友可以參考下2024-04-04

