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,
        },
    });
});
相关推荐
Aotman_几秒前
Vue el-table 字段自定义排序(进阶)
前端·javascript·vue.js·elementui·前端框架·ecmascript
Charonrise几秒前
完美解决Microsft Edge浏览器双击无法打开 双击无反应 无响应 不能用
前端·edge
华仔啊2 分钟前
这 5 个冷门 HTML 标签,让我直接删了100 行 JS 代码!
前端·html
西维6 分钟前
大屏、看板必备的丝滑技巧 — 数字滚动
前端·javascript·动效
前端工作日常10 分钟前
我学习到的AG-UI的功能:全面的交互支持
前端
LawrenceLan11 分钟前
Flutter 零基础入门(十三):late 关键字与延迟初始化
开发语言·前端·flutter·dart
深耕AI11 分钟前
【wordpress系列教程】03 网站页面的编辑
开发语言·前端
前端达人18 分钟前
2026年React数据获取的第六层:从自己写缓存到用React Query——减少100行代码的秘诀
前端·javascript·react.js·缓存·前端框架
2501_9481226320 分钟前
React Native for OpenHarmony 实战:Steam 资讯 App 通知设置实现
javascript·react native·react.js·游戏·ecmascript·harmonyos