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:
- 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
.
- Nếu có token, thêm nó vào header của mỗi yêu cầu với định dạng
- Lấy token từ localStorage:
- 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.
- Xử lý token hết hạn:
- Tạo instance của Axios:
- 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 statedata
.
- Xử lý lỗi:
setError(error);
: Lưu lỗi vào stateerror
nếu có.
- Thực hiện yêu cầu GET tới endpoint
- Dùng để thực hiện hàm
- 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.
- Khởi tạo state: