前端實(shí)現(xiàn)Token無感刷新的思路和具體實(shí)現(xiàn)方法
前言
在前端開發(fā)中,Token 無感刷新是一種常見的優(yōu)化技術(shù),用于在用戶無感知的情況下刷新過期的身份驗(yàn)證 Token,從而避免用戶因 Token 過期而需要重新登錄。以下是實(shí)現(xiàn) Token 無感刷新的思路和具體實(shí)現(xiàn)方法。
實(shí)現(xiàn)思路
Token 過期機(jī)制:
通常,身份驗(yàn)證 Token 有一個(gè)有效期(如 2 小時(shí))。
當(dāng) Token 過期后,用戶需要重新登錄或刷新 Token。
無感刷新的核心:
在 Token 過期前,通過刷新 Token 接口獲取新的 Token。
使用新的 Token 替換舊的 Token,并繼續(xù)用戶的請求。
實(shí)現(xiàn)步驟:
在請求攔截器中檢查 Token 是否即將過期。
如果 Token 即將過期,發(fā)起刷新 Token 的請求。
在響應(yīng)攔截器中處理 Token 過期的情況,重新發(fā)起失敗的請求。
具體實(shí)現(xiàn)
以下是一個(gè)基于 Axios 的 Token 無感刷新實(shí)現(xiàn)示例:
- 安裝 Axios
如果尚未安裝 Axios,可以通過以下命令安裝:
npm install axios
- 封裝 Axios 實(shí)例
創(chuàng)建一個(gè)封裝了 Token 無感刷新邏輯的 Axios 實(shí)例。
import axios from "axios";
// 創(chuàng)建 Axios 實(shí)例
const instance = axios.create({
baseURL: "https://api.example.com",
timeout: 10000,
});
// 存儲(chǔ) Token 和刷新 Token
let token = localStorage.getItem("token") || "";
let refreshToken = localStorage.getItem("refreshToken") || "";
// 請求攔截器
instance.interceptors.request.use(
(config) => {
// 如果 Token 存在,添加到請求頭
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 響應(yīng)攔截器
instance.interceptors.response.use(
(response) => {
return response;
},
async (error) => {
const originalRequest = error.config;
// 如果 Token 過期且未發(fā)起過刷新請求
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true; // 標(biāo)記為已發(fā)起刷新請求
try {
// 發(fā)起刷新 Token 的請求
const response = await axios.post("/refresh-token", {
refreshToken,
});
// 更新 Token 和刷新 Token
const { token: newToken, refreshToken: newRefreshToken } = response.data;
token = newToken;
refreshToken = newRefreshToken;
localStorage.setItem("token", newToken);
localStorage.setItem("refreshToken", newRefreshToken);
// 更新請求頭中的 Token
originalRequest.headers.Authorization = `Bearer ${newToken}`;
// 重新發(fā)起原始請求
return instance(originalRequest);
} catch (refreshError) {
// 刷新 Token 失敗,跳轉(zhuǎn)到登錄頁
localStorage.removeItem("token");
localStorage.removeItem("refreshToken");
window.location.href = "/login";
return Promise.reject(refreshError);
}
}
return Promise.reject(error);
}
);
export default instance;
- 使用封裝的 Axios 實(shí)例
在項(xiàng)目中使用封裝好的 Axios 實(shí)例發(fā)起請求。
import axiosInstance from "./axiosInstance";
const fetchData = async () => {
try {
const response = await axiosInstance.get("/data");
console.log(response.data);
} catch (error) {
console.error("請求失敗", error);
}
};
fetchData();
關(guān)鍵點(diǎn)解析
Token 存儲(chǔ):
將 Token 和刷新 Token 存儲(chǔ)在 localStorage 或 sessionStorage 中。
每次請求時(shí)從存儲(chǔ)中讀取 Token。
請求攔截器:
在請求攔截器中,將 Token 添加到請求頭。
響應(yīng)攔截器:
在響應(yīng)攔截器中,檢查響應(yīng)狀態(tài)碼是否為 401(未授權(quán))。
如果 Token 過期,發(fā)起刷新 Token 的請求。
刷新成功后,更新 Token 并重新發(fā)起原始請求。
刷新 Token 接口:
后端需要提供一個(gè)刷新 Token 的接口(如 /refresh-token),接收 refreshToken 并返回新的 token 和 refreshToken。
錯(cuò)誤處理:
如果刷新 Token 失敗,清除本地存儲(chǔ)的 Token 并跳轉(zhuǎn)到登錄頁。
進(jìn)一步優(yōu)化
Token 過期時(shí)間檢查:
在請求攔截器中檢查 Token 的剩余有效期。
如果 Token 即將過期(如剩余 5 分鐘),提前刷新 Token。
const isTokenExpired = (token) => {
const payload = JSON.parse(atob(token.split(".")[1]));
const exp = payload.exp * 1000; // 轉(zhuǎn)換為毫秒
return Date.now() >= exp - 5 * 60 * 1000; // 提前 5 分鐘刷新
};
instance.interceptors.request.use(
(config) => {
if (token && isTokenExpired(token)) {
// 發(fā)起刷新 Token 的請求
refreshToken()
.then((newToken) => {
token = newToken;
localStorage.setItem("token", newToken);
config.headers.Authorization = `Bearer ${newToken}`;
})
.catch(() => {
localStorage.removeItem("token");
window.location.href = "/login";
});
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
并發(fā)請求處理:
如果多個(gè)請求同時(shí)發(fā)現(xiàn) Token 過期,確保只發(fā)起一次刷新 Token 的請求。
使用一個(gè)標(biāo)志變量(如 isRefreshing)來控制刷新請求的并發(fā)。
安全性:
使用 HTTPS 加密傳輸 Token。
設(shè)置合理的 Token 有效期和刷新 Token 的有效期。
總結(jié)
通過 Axios 的請求攔截器和響應(yīng)攔截器,可以實(shí)現(xiàn) Token 的無感刷新,從而提升用戶體驗(yàn)。關(guān)鍵在于:
在 Token 過期前主動(dòng)刷新。
處理并發(fā)請求和錯(cuò)誤情況。
確保 Token 存儲(chǔ)和傳輸?shù)陌踩浴?/p>
這種方法適用于大多數(shù)前后端分離的項(xiàng)目,能夠有效減少用戶因 Token 過期而需要重新登錄的情況。
到此這篇關(guān)于前端實(shí)現(xiàn)Token無感刷新的思路和具體實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)前端Token無感刷新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Bootstrap3.0建站教程(一)之bootstrap表單元素排版
本文給大家介紹Bootstrap3.0建站教程(一)之bootstrap表單元素排版,本文給大家列舉了文字和輸入框前后排列和上下排列的實(shí)例代碼,有需要的朋友參考下吧2016-06-06
使用 JScript 創(chuàng)建 .exe 或 .dll 文件的方法
JScript 是由微軟開發(fā)的活動(dòng)腳本語言,基于 ECMAScript 規(guī)范實(shí)現(xiàn)。Internet Explorer 中的 JavaScript,實(shí)際上是指 JScript。2011-07-07
Javascript 正則表達(dá)式校驗(yàn)數(shù)字的簡單實(shí)例
下面小編就為大家?guī)硪黄狫avascript 正則表達(dá)式校驗(yàn)數(shù)字的簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11
javascript 哈希表(hashtable)的簡單實(shí)現(xiàn)
javascript中沒有像c#,java那樣的哈希表(hashtable)的實(shí)現(xiàn)。在js中,object屬性的實(shí)現(xiàn)就是hash表,因此只要在object上封裝點(diǎn)方法,簡單的使用obejct管理屬性的方法就可以實(shí)現(xiàn)簡單高效的hashtable。2010-01-01
利用JavaScript實(shí)現(xiàn)防抖節(jié)流函數(shù)的示例代碼
在開發(fā)中我們經(jīng)常會(huì)遇到一些高頻操作,比如:鼠標(biāo)移動(dòng),滑動(dòng)窗口,鍵盤輸入等等,節(jié)流和防抖就是對(duì)此類事件進(jìn)行優(yōu)化,降低觸發(fā)的頻率,以達(dá)到提高性能的目的。本文就教大家如何實(shí)現(xiàn)一個(gè)讓面試官拍大腿的防抖節(jié)流函數(shù),需要的可以參考一下2022-08-08
微信小程序?qū)崿F(xiàn)頁面浮動(dòng)導(dǎo)航
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)頁面浮動(dòng)導(dǎo)航,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01

