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,
        },
    });
});
相关推荐
sakiko_1 天前
UIKit学习笔记3-布局、滚动视图、隐藏或显示视图
前端·笔记·学习·objective-c·swift·uikit
RPGMZ1 天前
RPGMakerMZ 地图存档点制作 标题继续游戏直接读取存档
开发语言·javascript·游戏·游戏引擎·rpgmz·rpgmakermz
有一个好名字1 天前
Agent Loop —— 一切从那个 while 循环开始
前端·javascript·chrome
一天睡25小时1 天前
Claude Code 指令入门教程
前端
EF@蛐蛐堂1 天前
【js】浏览器滚动条优化组件OverlayScrollbars
开发语言·javascript·ecmascript
yingyima1 天前
正则表达式实战:从日志中精准提取关键字段
前端
TeamDev1 天前
如何在 DotNetBrowser 中使用本地 AI 模型
前端·后端·.net
谢尔登1 天前
10_从 React Hooks 本质看 useState
前端·ubuntu·react.js
辰同学ovo1 天前
从全局登录状态管理学习 Redux
前端·javascript·学习·react.js
爱看书的小沐1 天前
【小沐杂货铺】基于Three.js绘制三维艺术画廊3DArtGallery (Three.js,WebGL)
javascript·3d·webgl·three.js·babylon.js·三维画廊