- html代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/theme-chalk/index.css" rel="stylesheet">
</head><body><div><button class="el-button el-button--primary">获取token</button><button class="el-button el-button--primary">测试</button><button class="el-button el-button--primary">刷新</button></div><script src="https://cdn.bootcdn.net/ajax/libs/axios/1.9.0/axios.js"></script><script>const getToken = () => {return localStorage.getItem('token');}const setToken = (token) => {localStorage.setItem('token', token);}axios.defaults.baseURL = 'http://localhost:18565';axios.interceptors.request.use(config => {config.headers.authorization = getToken();return config;}, error => {return Promise.reject(error);});let isRefreshing = false;let queue = [];axios.interceptors.response.use(response => {return response.data;}, error => {if ([403, 401].includes(error.status)) {if (!isRefreshing) {isRefreshing = true;return axios.request({ url: '/test/api/refresh-token', method: 'post' }).then(res => {setToken(res.data.token);queue.forEach(callback => callback());queue = [];return axios.request(error.config);}).finally(() => {isRefreshing = false;})}return new Promise((resolve, reject) => {queue.push(() => {axios.request(error.config)});});}return Promise.reject(error);});const test1 = document.querySelector('.el-button--primary:nth-child(1)');const test2 = document.querySelector('.el-button--primary:nth-child(2)');const refresh = document.querySelector('.el-button--primary:nth-child(3)');test1.addEventListener('click', () => {axios.request({url: '/test/api/get-token',method: 'get',}).then(res => {localStorage.clear();console.log(res.data.token, '---------get-token');setToken(res.data.token);});});test2.addEventListener('click', () => {axios.request({url: '/test/api/protected',method: 'get',headers: {authorization: getToken()}}).then(res => {console.log(res, '---------protected');});});refresh.addEventListener('click', () => {axios.request({url: '/test/api/refresh-token',method: 'post',}).then(res => {console.log(res, '---------refresh-token');});});</script>
</body></html>
- server端代码,可以使用mock进行模拟
const expireTime = 10 * 1000;
function generateToken() {return (Date.now() + expireTime).toString();
}
router.get('/api/get-token', (req, res) => {const token = generateToken();res.json({code: 200,msg: 'token获取成功',data: {token,},});
});
router.get('/api/protected', (req, res) => {const token = req.headers['authorization'];let isExpire = parseInt(token) >= Date.now();if (!token || !isExpire) {return res.status(401).json({code: 401, msg: 'token已过期,请刷新token'});}res.json({code: 200,msg: '调用成功',data: {msg: '调用成功',},});
});
router.post('/api/refresh-token', async (req, res) => {await sleep(5 * 1000);const newToken = generateToken();res.json({code: 200,msg: 'token刷新成功',data: {token: newToken,},});
});