前端 Token 无感刷新:基于 Axios 拦截器的完整实现方案
本文详细解析前端 Token 无感刷新的核心思路,通过 Axios 请求与响应拦截器实现自动续期。涵盖 Token 存储、过期检测、刷新接口调用及错误处理机制,重点解决多请求并发刷新导致的重复请求问题,并提供基于 JWT 解析的提前刷新策略与完整代码示例,提升前后端分离项目的用户体验。
前言
在前端开发实践中,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无感刷新内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
Mock.js 拦截失效或数据格式错误的常见原因及排查
2026-11-05 10:11:59
Java和JavaScript名字像但没关系:辨析Java、JavaWeb与JS
2026-11-04 09:30:54
CodePen、JSFiddle与RunJS对比:哪款JS在线运行工具更适合你?
2026-11-03 16:46:57
JS 统计图渲染空白或报错怎么排查?常见问题解决指南
2026-11-03 09:49:40
flv.js 常见报错 MediaError 与解码失败排查指南
2026-11-02 10:29:29
