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,
        },
    });
});
相关推荐
涛涛ing7 分钟前
Navigation API正式Baseline:那个让无数前端头疼的History API,终于可以退休了
前端
Hilaku14 分钟前
为什么我劝应届生不要去创业公司写前端?
前端·javascript·程序员
郑州光合科技余经理17 分钟前
出海外卖平台:支付对接为什么要和下单收款分开
android·java·开发语言·前端·后端·php·ai编程
data analyse 45631 分钟前
前端自建访问统计,访客标识怎么设计才稳?Cookie、本地存储与设备指纹的取舍
前端·数据分析
终端安全笔记36 分钟前
配置锁状态那一栏查的是什么:报告里几项各自指向什么风险
android·前端·安全·ios
恋猫de小郭1 小时前
Kotlin Toolchain 0.13,JetBrains 推荐 KMP 都切换到到全新工具链
android·前端·flutter
高级程序源1 小时前
hive电商平台商品销售数据分析与趋势预测45659-计算机课程设计、毕业设计
vue.js·hive·spring boot·mysql·数据分析·django·课程设计
我是人✓1 小时前
Java面向对象核心特性深度解析
java·前端·算法
晓得迷路了1 小时前
栗子前端技术周刊第 149 期 - Vite+ 1.0、Preact 11、Next.js 16.4...
前端·javascript·react.js
IT_陈寒1 小时前
为什么我的Vue组件总是莫名其妙更新?
前端·人工智能·后端