Axios 拦截器示例(JWT 登录与自动刷新)

1. 安装 axios

首先,确保你已经安装了 axios

npm install axios

2. 设置 Axios 拦截器

import axios from 'axios';

// 创建一个 axios 实例
const axiosInstance = axios.create({
  baseURL: 'http://localhost:8000/',  // 后端 API 地址
  timeout: 10000,  // 设置超时时间
});

// 请求拦截器
axiosInstance.interceptors.request.use(
  config => {
    // 从 localStorage 获取 access_token
    const token = localStorage.getItem('access_token');
    
    if (token) {
      // 如果存在 access_token,就将它添加到请求头
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    
    return config;
  },
  error => {
    // 请求失败时的处理
    return Promise.reject(error);
  }
);

// 响应拦截器
axiosInstance.interceptors.response.use(
  response => {
    return response;
  },
  async error => {
    const originalRequest = error.config;
    
    // 如果响应的错误是 token 过期
    if (error.response && error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      
      try {
        // 尝试用 refresh_token 刷新 access_token
        const refreshToken = localStorage.getItem('refresh_token');
        
        const response = await axios.post('http://localhost:8000/api/token/refresh/', {
          refresh: refreshToken,
        });

        const { access } = response.data;

        // 更新 access_token
        localStorage.setItem('access_token', access);

        // 设置新的 access_token 并重新发起原始请求
        axiosInstance.defaults.headers['Authorization'] = `Bearer ${access}`;
        originalRequest.headers['Authorization'] = `Bearer ${access}`;
        
        return axiosInstance(originalRequest);
      } catch (err) {
        // 刷新 token 失败时的处理(例如 token 已过期或无效)
        console.error('Token refresh failed:', err);
        // 这里可以选择登出操作或其他处理
        localStorage.removeItem('access_token');
        localStorage.removeItem('refresh_token');
        window.location.href = '/login';  // 重定向到登录页面
      }
    }
    
    return Promise.reject(error);
  }
);

export default axiosInstance;

3. 如何使用这个 Axios 实例

在你的项目中,使用 axiosInstance 来进行 API 请求,它会自动处理 Authorization 头以及 token 刷新逻辑。

import axiosInstance from './path/to/axiosInstance';

// 示例:登录请求
function login(username, password) {
  axiosInstance.post('api/login/', { username, password })
    .then(response => {
      const { access, refresh } = response.data;
      localStorage.setItem('access_token', access);
      localStorage.setItem('refresh_token', refresh);
    })
    .catch(error => {
      console.error('Login failed:', error);
    });
}

// 示例:获取受保护资源
function getProtectedData() {
  axiosInstance.get('api/protected-endpoint/')
    .then(response => {
      console.log('Protected data:', response.data);
    })
    .catch(error => {
      console.error('Failed to fetch protected data:', error);
    });
}

4. 解释代码

  1. 请求拦截器:每次请求发送前都会检查 localStorage 中是否有 access_token,如果有,它会将 access_token 加入请求头 Authorization 中。

  2. 响应拦截器

    • 如果返回的状态码是 401(即 token 过期或无效),拦截器会使用存储的 refresh_token 来刷新 access_token
    • 刷新成功后,它会将新的 access_token 存储到 localStorage 中,并重新发起原始请求。
    • 如果刷新失败(例如,refresh_token 已失效),会移除所有 token,并重定向到登录页面。

这样,每个 API 请求都会自动带上最新的 access_token,并且在 token 过期时会自动刷新,保证用户的会话始终有效。

posted @ 2024-11-15 17:07  林汉州win  阅读(67)  评论(0编辑  收藏  举报