
在现代的单页应用(SPA)中,用户认证是一个至关重要的部分。为了保护用户的信息安全,通常会使用JWT(JSON Web Token)进行身份验证。然而,Token通常有一定的有效期,在有效期到期后,用户需要重新登录以获取新Token,这可能会影响用户体验。为了解决这个问题,我们可以实现Token的无感刷新机制,允许用户在不知觉中自动更新Token。
第一步:设置Axios实例
我们将使用Axios创建一个实例,并设置请求和响应拦截器。确保你已经安装了Axios:
npm install axios
然后创建一个 axiosInstance.js文件:
import axios from 'axios';
const axiosInstance = axios.create({
baseURL: 'https://api.example.com', // 替换为你的 API 地址
});
// 添加请求拦截器
axiosInstance.interceptors.request.use(config => {
const token = localStorage.getItem('token'); // 从存储中获取当前的 Token
if (token) {
config.headers['Authorization'] = `Bearer ${token}`; // 将 Token 加入请求头
}
return config;
}, error => {
return Promise.reject(error);
});第二步:添加响应拦截器
我们需要处理401错误(即未授权)并尝试刷新Token。在响应拦截器中,我们监控请求的状态,如果遇到Token过期的情况,则发起刷新Token的请求。
let isRefreshing = false;
let pendingRequests = [];
axiosInstance.interceptors.response.use(response => {
return response;
}, async error => {
const originalRequest = error.config;
// 检查是否是401错误以及是否已经在刷新Token
if (error.response.status === 401 && !isRefreshing) {
isRefreshing = true;
try {
const refreshToken = localStorage.getItem('refreshToken'); // 获取 Refresh Token
const response = await axios.post('/auth/refresh', { token: refreshToken }); // 刷新 Token 的请求
const { token } = response.data; // 假设新的 Token 在这里返回
localStorage.setItem('token', token); // 保存新 Token
// 重试原始请求
pendingRequests.forEach(callback => callback(token));
pendingRequests = [];
return axiosInstance(originalRequest); // 重发原始请求
} catch (err) {
// 如果刷新失败,清除 Token 并重定向到登录页面等
localStorage.removeItem('token');
localStorage.removeItem('refreshToken');
window.location.href = '/login'; // 跳转到登录页
return Promise.reject(err);
} finally {
isRefreshing = false;
}
}
// 如果正在刷新Token,将后续请求加入队列
if (isRefreshing) {
return new Promise((resolve, reject) => {
pendingRequests.push((token) => {
originalRequest.headers['Authorization'] = `Bearer ${token}`;
resolve(axiosInstance(originalRequest));
});
});
}
return Promise.reject(error);
});第三步:用户登录与登出
当用户登录成功时,我们需要保存Token和Refresh Token。以下是一个简单的登录函数示例:
async function login(username, password) {
const response = await axios.post('/auth/login', { username, password });
const { token, refreshToken } = response.data; // 假设返回数据中包含 Token 和 Refresh Token
localStorage.setItem('token', token);
localStorage.setItem('refreshToken', refreshToken);
}用户登出时,我们需要清理存储的 Token:
function logout() {
localStorage.removeItem('token');
localStorage.removeItem('refreshToken');
window.location.href = '/login'; // 跳转到登录页
}第四步:使用Axios实例
最后,在你的组件或服务中使用配置好的Axios实例进行API请求。
axiosInstance.get('/some-protected-route')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});








