AXIN9 – Sử dụng Interceptors để thêm token vào mọi request
5 mins read

AXIN9 – Sử dụng Interceptors để thêm token vào mọi request

Dưới đây là một ví dụ chi tiết hơn về cách xử lý các token hết hạn hoặc yêu cầu một token mới trong một ứng dụng React sử dụng Axios. Ví dụ này sẽ bao gồm việc tự động làm mới token khi token hiện tại hết hạn.

Bước 1: Tạo Axios Instance và thiết lập Interceptor

Tạo file axiosInstance.js:

  • File này sẽ chứa cấu hình của Axios instance và các Interceptors.
import axios from 'axios';

// Tạo instance của Axios với base URL
const axiosInstance = axios.create({
  baseURL: 'https://api.example.com', // Thay thế bằng URL API của bạn
});

let isRefreshing = false;
let failedQueue = [];

const processQueue = (error, token = null) => {
  failedQueue.forEach(prom => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(token);
    }
  });

  failedQueue = [];
};

// Thêm Interceptor cho các yêu cầu để thêm token vào header
axiosInstance.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('accessToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// Thêm Interceptor cho các phản hồi để xử lý token hết hạn
axiosInstance.interceptors.response.use(
  (response) => {
    return response;
  },
  async (error) => {
    const originalRequest = error.config;

    if (error.response.status === 401 && !originalRequest._retry) {
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject });
        }).then(token => {
          originalRequest.headers['Authorization'] = 'Bearer ' + token;
          return axios(originalRequest);
        }).catch(err => {
          return Promise.reject(err);
        });
      }

      originalRequest._retry = true;
      isRefreshing = true;

      const refreshToken = localStorage.getItem('refreshToken');
      return new Promise((resolve, reject) => {
        axios.post('/auth/refresh-token', { token: refreshToken })
          .then(({ data }) => {
            localStorage.setItem('accessToken', data.accessToken);
            localStorage.setItem('refreshToken', data.refreshToken);
            axiosInstance.defaults.headers.common['Authorization'] = 'Bearer ' + data.accessToken;
            originalRequest.headers['Authorization'] = 'Bearer ' + data.accessToken;
            processQueue(null, data.accessToken);
            resolve(axios(originalRequest));
          })
          .catch((err) => {
            processQueue(err, null);
            reject(err);
          })
          .finally(() => {
            isRefreshing = false;
          });
      });
    }

    return Promise.reject(error);
  }
);

export default axiosInstance;

Bước 2: Sử dụng Axios Instance trong React Component

Tạo Component để sử dụng Axios Instance:

  • File này sẽ chứa một component React sử dụng Axios instance để thực hiện các yêu cầu HTTP.
import React, { useEffect, useState } from 'react';
import axios from './axiosInstance';

const FetchDataWithToken = () => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        // Thực hiện yêu cầu GET tới endpoint '/protected-data'
        const response = await axios.get('/protected-data');
        setData(response.data);
      } catch (error) {
        setError(error);
      }
    };

    fetchData();
  }, []);

  if (error) return <div>Error: {error.message}</div>;
  if (!data) return <div>Loading...</div>;

  return (
    <div>
      <h1>Protected Data:</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

export default FetchDataWithToken;

Giải thích chi tiết:

  1. Cấu hình Axios Instance (axiosInstance.js):
    • Tạo instance của Axios: axios.create({ baseURL: 'https://api.example.com' })
      • Tạo một instance của Axios với URL cơ bản trỏ tới API của bạn.
    • Thiết lập Interceptor cho yêu cầu:
      • axiosInstance.interceptors.request.use:
        • Lấy token từ localStorage: const token = localStorage.getItem('accessToken');
          • Lấy token đã lưu trữ trong localStorage (giả sử token được lưu ở đó sau khi người dùng đăng nhập).
        • Thêm token vào header của yêu cầu: config.headers.Authorization = Bearer ${token}“
          • Nếu có token, thêm nó vào header của mỗi yêu cầu với định dạng Bearer.
    • Thiết lập Interceptor cho phản hồi:
      • axiosInstance.interceptors.response.use:
        • Xử lý token hết hạn:
          • Kiểm tra nếu mã trạng thái là 401 và chưa retry, thử refresh token.
          • Nếu đang refreshing, đưa yêu cầu vào hàng đợi.
          • Nếu không, gửi yêu cầu refresh token và xử lý lại các yêu cầu trong hàng đợi.
  2. Component React (FetchDataWithToken.js):
    • Khởi tạo state:
      • const [data, setData] = useState(null);
      • const [error, setError] = useState(null);
      • Tạo state để lưu trữ dữ liệu nhận được và lỗi nếu có.
    • useEffect:
      • Dùng để thực hiện hàm fetchData ngay khi component được render.
      • Hàm fetchData:
        • Thực hiện yêu cầu GET tới endpoint /protected-data bằng cách sử dụng Axios instance đã tạo.
        • Xử lý phản hồi:
          • setData(response.data);: Lưu dữ liệu trả về vào state data.
        • Xử lý lỗi:
          • setError(error);: Lưu lỗi vào state error nếu có.
    • Render dữ liệu:
      • Nếu có lỗi: Hiển thị thông báo lỗi.
      • Nếu dữ liệu đang được tải: Hiển thị thông báo đang tải.
      • Nếu có dữ liệu: Hiển thị dữ liệu dưới dạng JSON.

Nguồn tham khảo:

Leave a Reply

Your email address will not be published. Required fields are marked *