1. Đặt vấn đề
Chắc hẳn rằng trong quá trình làm việc của anh em front-end đã từng tiếp xúc với hai ông thần là
accessToken và refreshToken phải không nào? Nó đơn giản là xác thực phiên đăng nhập của anh xem còn hạn sử dụng hay không nếu như accessToken hết hạn thì chúng ta sẽ gọi refreshToken để trả về accessToken mới. Vậy nếu nhưng chúng ta có 10 request cùng lúc mà bị hết hạn thì lại gọi 10 lần refreshToken thì thật sự không ổn một chút nào2. Giải pháp
để giải quyết câu hỏi trên thì chúng ta cần có một ông thần đắc lực để giải vấn đề này đó chính là
Axios Axios là gì: Axios là một thư viện HTTP client dựa trên Promises, giúp gửi và nhận request dễ dàng trong JavaScript (Node.js & trình duyệt).
Ưu điểm và tính năng của Axios:
- Tạo request từ trình duyệt bằng XMLHttpRequest
- Tạo request từ node.js bằng http
- Hỗ trợ Promise API
- Đón chặn request và response
- Biến đổi dữ liệu request và response
- Bãi bỏ request
- Tự động chuyển đổi cho dữ liệu JSON
- Hỗ trợ phía client bảo vệ chống lại XSRF
3. Cài đặt và cấu hình Axios
Cài đặt
npm install axios
Cấu hình
import axios from 'axios'; import { API_URL, lOCAL_STORAGE_FIELDS } from '@/constants'; const api = axios.create({ baseURL: API_URL, headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, });
Cấu hình interceptors cho các request
api.interceptors.request.use((config) => { const token = localStorage.getItem(lOCAL_STORAGE_FIELDS.ACCESS_TOKEN) ?? ''; // các request gưởi đi sẽ dược tự động thêm accessToken vào headers config.headers.Authorization = token ? `Bearer ${JSON.parse(token)}` : null; return config; });
Cấu hình interceptors cho các response trả về nếu gặp lỗi
401 Unauthorizedapi.interceptors.response.use( async (response) => { const config = response.config; const code = response.data?.code if (code && code === 401) { const newAccessToken handleRequest(); config.headers.Authorization = `Bearer ${newAccessToken}`; return api(config); } return response; }, (error) => { return Promise.reject(error); } );
khi dữ liệu trả về bị lỗi 401 thì
Axios sẽ gọi hàm handleRequest để lấy token mới và gán lại Authorization headers cho những request tiếp theo, vậy làm sao để chỉ gọi duy nhất một lần làm mới refreshToken chúng ta hãy cùng nhau tìm hiểu phương pháp dưới đây4. Ngăn chặn gọi refreshToken khi có nhiều request hết hạn
để ngăn chặn việc gọi nhiều lần
refreshToken ta sẽ đặt một cờ là refreshTokenRequestimport axios from 'axios'; import { API_URL, lOCAL_STORAGE_FIELDS } from '@/constants'; let refreshTokenRequest: null | Promise<string> = null; const api = axios.create({ baseURL: API_URL, headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, });
chúng ta sẽ sử dụng cờ
refreshTokenRequest trong hàm handleRequest như sau:const handleRequest = async () => { refreshTokenRequest = refreshTokenRequest ? refreshTokenRequest : refreshToken(); const newAccessToken = await refreshTokenRequest; refreshTokenRequest = null; return newAccessToken; };
giải thích thi response trả về với code 401 thì Axios interceptors sẽ gọi hàm
handleRequest ví dụ chúng ta có 10 request bị 401 Unauthorized thì handleRequest sẽ được gọi, nó sẽ kiểm tra rằng refreshTokenRequest đã có giá trị gán hay chưa, nếu chưa thì nó sẽ gán vào đó 1 hàm refreshToken và nếu như đã gán thì nói sẽ chỉ dùng chung duy nhất một lần gọi refreshToken đã được gán vào trước đó. vậy là vấn đề được giải quyết.5. Kết quả
Thành quả đạt được là dùng nếu có 100 request bị hết hạn đồng thời thì cũng chỉ có duy nhất một lần refreshToken được gọi
6. Tổng kết
Qua bài viết này chúng ta đã tìm hiểu Axios là gì, cách cấu hình Axios với interceptors như thế nào và cách ngăn chặn gọi refreshToken nhiều lần khi có nhiều request hết hạn đồng thời. Nếu bạn thấy bài viết này hữu ích, hãy chia sẻ bài viết này để nhiều người biết đến nhé.
