前端實現(xiàn)Token無感刷新的思路和具體實現(xiàn)方法
前言
在前端開發(fā)中,Token 無感刷新是一種常見的優(yōu)化技術,用于在用戶無感知的情況下刷新過期的身份驗證 Token,從而避免用戶因 Token 過期而需要重新登錄。以下是實現(xiàn) Token 無感刷新的思路和具體實現(xiàn)方法。
實現(xiàn)思路
Token 過期機制:
通常,身份驗證 Token 有一個有效期(如 2 小時)。
當 Token 過期后,用戶需要重新登錄或刷新 Token。
無感刷新的核心:
在 Token 過期前,通過刷新 Token 接口獲取新的 Token。
使用新的 Token 替換舊的 Token,并繼續(xù)用戶的請求。
實現(xiàn)步驟:
在請求攔截器中檢查 Token 是否即將過期。
如果 Token 即將過期,發(fā)起刷新 Token 的請求。
在響應攔截器中處理 Token 過期的情況,重新發(fā)起失敗的請求。
具體實現(xiàn)
以下是一個基于 Axios 的 Token 無感刷新實現(xiàn)示例:
- 安裝 Axios
如果尚未安裝 Axios,可以通過以下命令安裝:
npm install axios
- 封裝 Axios 實例
創(chuàng)建一個封裝了 Token 無感刷新邏輯的 Axios 實例。
import axios from "axios"; // 創(chuàng)建 Axios 實例 const instance = axios.create({ baseURL: "https://api.example.com", timeout: 10000, }); // 存儲 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); } ); // 響應攔截器 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; // 標記為已發(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 實例
在項目中使用封裝好的 Axios 實例發(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();
關鍵點解析
Token 存儲:
將 Token 和刷新 Token 存儲在 localStorage 或 sessionStorage 中。
每次請求時從存儲中讀取 Token。
請求攔截器:
在請求攔截器中,將 Token 添加到請求頭。
響應攔截器:
在響應攔截器中,檢查響應狀態(tài)碼是否為 401(未授權)。
如果 Token 過期,發(fā)起刷新 Token 的請求。
刷新成功后,更新 Token 并重新發(fā)起原始請求。
刷新 Token 接口:
后端需要提供一個刷新 Token 的接口(如 /refresh-token),接收 refreshToken 并返回新的 token 和 refreshToken。
錯誤處理:
如果刷新 Token 失敗,清除本地存儲的 Token 并跳轉(zhuǎn)到登錄頁。
進一步優(yōu)化
Token 過期時間檢查:
在請求攔截器中檢查 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ā)請求處理:
如果多個請求同時發(fā)現(xiàn) Token 過期,確保只發(fā)起一次刷新 Token 的請求。
使用一個標志變量(如 isRefreshing)來控制刷新請求的并發(fā)。
安全性:
使用 HTTPS 加密傳輸 Token。
設置合理的 Token 有效期和刷新 Token 的有效期。
總結
通過 Axios 的請求攔截器和響應攔截器,可以實現(xiàn) Token 的無感刷新,從而提升用戶體驗。關鍵在于:
在 Token 過期前主動刷新。
處理并發(fā)請求和錯誤情況。
確保 Token 存儲和傳輸?shù)陌踩浴?/p>
這種方法適用于大多數(shù)前后端分離的項目,能夠有效減少用戶因 Token 過期而需要重新登錄的情況。
到此這篇關于前端實現(xiàn)Token無感刷新的思路和具體實現(xiàn)方法的文章就介紹到這了,更多相關前端Token無感刷新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
微信小程序使用checkbox顯示多項選擇框功能【附源碼下載】
這篇文章主要介紹了微信小程序使用checkbox顯示多項選擇框功能,涉及相關事件綁定與元素遍歷操作技巧,并附帶源碼供讀者下載參考,需要的朋友可以參考下2017-12-12webpack file-loader和url-loader的區(qū)別
這篇文章主要介紹了webpack file-loader和url-loader的區(qū)別,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01詳解JS轉(zhuǎn)換數(shù)值函數(shù)Number()、parseInt()、parseFloat()
JS中有三種函數(shù)可以將非數(shù)值轉(zhuǎn)換成數(shù)值:Number()、parseInt()和parseFloat()。接下來通過本文詳細的給大家介紹JS轉(zhuǎn)換數(shù)值函數(shù)Number()、parseInt()、parseFloat()的實例代碼,感興趣的朋友一起看看吧2018-08-08