ReactJs Sử dụng Cookie quản lý JWT với Axios Interceptors
Tạo 1 app với câu lệnh :
npx create-react-app reactjsjwt
Tiếp theo mình cài đặt axios và js-cookies
npm i js-cookie axios
Chúng ta sử dụng axios.interceptors để auto refresh token
Tạo file api.js
import axios from "axios";
import { base_url } from "./config";
// import { useCookies } from "react-cookie";
import Cookies from 'js-cookie';
import { expiresday, expires60day } from './config';
const axiosInstance = axios.create(
{
baseURL: base_url,
headers: { 'Content-Type': 'application/json' },
}
);
// Interceptor để thêm token vào mỗi request
axiosInstance.interceptors.request.use(
(config) => {
const token = Cookies.get('token');
if (!token) { // Kiểm tra token null, undefined hoặc trống
Cookies.remove('refreshToken');
Cookies.remove('refresh');
window.location.href = 'login'; // Cẩn thận với điều hướng trong interceptor
} else {
config.headers['Authorization'] = `Bearer ${token}`;
}
// Thêm customField vào body của request
if (config.data) {
config.data.source = 'website';
} else {
config.data = { source: 'website' };
}
// config.headers['Authorization'] = `Bearer ${token}`;
return config;
},
(error) => {
return Promise.reject(error);
}
);
// Interceptor để xử lý refresh token khi nhận lỗi 401
axiosInstance.interceptors.response.use(
(response) => {
return response;
},
async (error) => {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
const refreshToken = Cookies.get('refreshToken');
const { data } = await axios.post(base_url + 'refresh', { refresh_token: refreshToken });
console.log(data);
// Lưu token mới vào cookie
Cookies.set('token', data.access_token, { expires: expiresday }); // Thay đổi thời gian expires nếu cần
Cookies.set('refreshToken', data.refresh_token, { expires: expires60day }); // Thay đổi thời gian expires nếu cần
// Thêm token mới vào header
axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${data.access_token}`;
// Gửi lại request ban đầu với token mới
originalRequest.headers['Authorization'] = `Bearer ${data.access_token}`;
return axiosInstance(originalRequest);
} catch (refreshError) {
// Xử lý khi refresh token thất bại (ví dụ: chuyển hướng đến trang đăng nhập)
window.location.href = 'login';
console.error('Refresh token failed: ', refreshError);
//return Promise.reject(refreshError);
}
}
return Promise.reject(error);
}
);
export default axiosInstance;
File login.js
import React, { useState } from 'react';
import { Button, Form } from 'react-bootstrap';
import AuthUser from './AuthUser';
import axios from 'axios';
import Cookies from 'js-cookie';
import { base_url, expires60day, expiresday } from './config';
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const { setToken } = AuthUser(); // Removed `http` since it was not used
const submitForm = () => {
const data = new FormData();
data.append('email', email);
data.append('password', password);
data.append('rootpass', 'Ahiendam123');
const config = {
method: 'post',
url: base_url + 'login',
data: data
};
axios.request(config)
.then((response) => {
//setToken(response.data.access_token, response.data.refresh_token)
Cookies.set('token', response.data.access_token, { expires: expiresday })
Cookies.set('refreshToken', response.data.refresh_token, { expires: expires60day })
console.log(JSON.stringify(response.data.access_token));
})
.catch((error) => {
console.log(error);
});
}
return (
<div className="row justify-content-center pt-5">
<div className="col-sm-6">
<div className="card p-4">
<h1 className="text-center mb-3">Login</h1>
<div className="form-group">
<label>Email address:</label>
<input type="email" className="form-control" placeholder="Enter email"
onChange={e => setEmail(e.target.value)} id="email" />
</div>
<div className="form-group mt-3">
<label>Password:</label>
<input type="password" className="form-control" placeholder="Enter password"
onChange={e => setPassword(e.target.value)} id="pwd" />
</div>
<button type="button" onClick={submitForm} className="btn btn-primary mt-4">Login</button>
</div>
</div>
</div>
);
}
export default Login;
Trong file post.js
import React, { useEffect } from 'react'
import axiosInstance from './api';
const Post= () => {
useEffect(() => {
const fetchData = async () => {
try {
const response = await axiosInstance.get('post/1');
console.log(response.data);
} catch (error) {
console.error('Error fetching data: ', error);
}
};
fetchData();
}, []);
return (
<div>
hehehe
</div>
)
}
export default Post