
在现代的单页应用(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);
  });









