前端实现Token无感刷新的思路和具体实现方法
作者:束尘
前言
在前端开发中,Token 无感刷新是一种常见的优化技术,用于在用户无感知的情况下刷新过期的身份验证 Token,从而避免用户因 Token 过期而需要重新登录。以下是实现 Token 无感刷新的思路和具体实现方法。
实现思路
Token 过期机制:
通常,身份验证 Token 有一个有效期(如 2 小时)。
当 Token 过期后,用户需要重新登录或刷新 Token。
无感刷新的核心:
在 Token 过期前,通过刷新 Token 接口获取新的 Token。
使用新的 Token 替换旧的 Token,并继续用户的请求。
实现步骤:
在请求拦截器中检查 Token 是否即将过期。
如果 Token 即将过期,发起刷新 Token 的请求。
在响应拦截器中处理 Token 过期的情况,重新发起失败的请求。
具体实现
以下是一个基于 Axios 的 Token 无感刷新实现示例:
- 安装 Axios
如果尚未安装 Axios,可以通过以下命令安装:
npm install axios
- 封装 Axios 实例
创建一个封装了 Token 无感刷新逻辑的 Axios 实例。
import axios from "axios"; // 创建 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 过期且未发起过刷新请求 if (error.response.status === 401 && !originalRequest._retry) { originalRequest._retry = true; // 标记为已发起刷新请求 try { // 发起刷新 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}`; // 重新发起原始请求 return instance(originalRequest); } catch (refreshError) { // 刷新 Token 失败,跳转到登录页 localStorage.removeItem("token"); localStorage.removeItem("refreshToken"); window.location.href = "/login"; return Promise.reject(refreshError); } } return Promise.reject(error); } ); export default instance;
- 使用封装的 Axios 实例
在项目中使用封装好的 Axios 实例发起请求。
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 添加到请求头。
响应拦截器:
在响应拦截器中,检查响应状态码是否为 401(未授权)。
如果 Token 过期,发起刷新 Token 的请求。
刷新成功后,更新 Token 并重新发起原始请求。
刷新 Token 接口:
后端需要提供一个刷新 Token 的接口(如 /refresh-token),接收 refreshToken 并返回新的 token 和 refreshToken。
错误处理:
如果刷新 Token 失败,清除本地存储的 Token 并跳转到登录页。
进一步优化
Token 过期时间检查:
在请求拦截器中检查 Token 的剩余有效期。
如果 Token 即将过期(如剩余 5 分钟),提前刷新 Token。
const isTokenExpired = (token) => { const payload = JSON.parse(atob(token.split(".")[1])); const exp = payload.exp * 1000; // 转换为毫秒 return Date.now() >= exp - 5 * 60 * 1000; // 提前 5 分钟刷新 }; instance.interceptors.request.use( (config) => { if (token && isTokenExpired(token)) { // 发起刷新 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); } );
并发请求处理:
如果多个请求同时发现 Token 过期,确保只发起一次刷新 Token 的请求。
使用一个标志变量(如 isRefreshing)来控制刷新请求的并发。
安全性:
使用 HTTPS 加密传输 Token。
设置合理的 Token 有效期和刷新 Token 的有效期。
总结
通过 Axios 的请求拦截器和响应拦截器,可以实现 Token 的无感刷新,从而提升用户体验。关键在于:
在 Token 过期前主动刷新。
处理并发请求和错误情况。
确保 Token 存储和传输的安全性。
这种方法适用于大多数前后端分离的项目,能够有效减少用户因 Token 过期而需要重新登录的情况。
到此这篇关于前端实现Token无感刷新的思路和具体实现方法的文章就介绍到这了,更多相关前端Token无感刷新内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!