axios无感刷新token

  1. html代码
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>
  1. server端代码,可以使用mock进行模拟
js 复制代码
const expireTime = 10 * 1000;
// 生成简单的token字符串
function generateToken() {
    // 生成一个随机字符串作为token
    return (Date.now() + expireTime).toString();
}

// 获取初始token接口
// 前端首次调用此接口获取token
router.get('/api/get-token', (req, res) => {
    const token = generateToken();
    res.json({
        code: 200,
        msg: 'token获取成功',
        data: {
            token,
        },
    });
});

// 受保护的接口,调用次数超过限制就返回token过期
router.get('/api/protected', (req, res) => {
    // 从请求头获取token,前端需在请求头加authorization: token
    const token = req.headers['authorization'];
    let isExpire = parseInt(token) >= Date.now();
    // 检查token是否存在且有效
    if (!token || !isExpire) {
        // 没有token或token无效
        return res.status(401).json({code: 401, msg: 'token已过期,请刷新token'});
    }
    res.json({
        code: 200,
        msg: '调用成功',
        data: {
            msg: '调用成功',
        },
    });
});

// 刷新token接口,返回新token并重置计数
router.post('/api/refresh-token', async (req, res) => {
    await sleep(5 * 1000);
    const newToken = generateToken();
    res.json({
        code: 200,
        msg: 'token刷新成功',
        data: {
            token: newToken,
        },
    });
});
相关推荐
平头哥技术团队17 小时前
Day 16 | 用 ul、ol、li 一个标签,把散资料收成有序的技能清单页
开发语言·前端·html·html5
代码青铜z17 小时前
不会写代码做小程序,模板开发和AI 编程靠谱吗?创业前先看这 5 件事
前端
小傅哥17 小时前
Java + DDD,1:1 复刻 Deepseek Harness 项目
前端·后端·ai编程
积硅步致千里17 小时前
Word 里的 .wmf 其实是 EMF:一次 metafile 转 PNG 排障
前端·后端
mayaairi17 小时前
Vue2 组件通讯(二):ref、自定义事件与provide/inject实战
前端·javascript·vue.js
开开心心就好18 小时前
PDF图片去水印软件,支持批量处理页面
前端·javascript·人工智能·智能手机·pdf·语音识别
爱敲代码的小杨.18 小时前
【Spring】Spring Web MVC
前端·spring·mvc
我的世界洛天依18 小时前
【胡桃讲编程】JS 入门第 1 课:Hello World,开启你的 JavaScript 编程之旅
javascript
是立不是利18 小时前
深入理解JavaScript事件委托
开发语言·前端·javascript
晴天1618 小时前
React 版本迭代解析:从15到19 核心差异-Day40
前端·react.js·前端框架