Vue3 + Axios双Token刷新解决方案

在现代前端开发中,使用 API 进行数据交互时,我们常常会遇到身份认证的问题。为了提高安全性,许多应用采用了Token 机制,如JWT(JSON Web Token) 来管理用户的身份状态。本文将介绍如何在 Vue3 项目中使用 Axios 实现双 Token 刷新机制,确保用户体验流畅的同时提高安全性。

前置条件

  1. 本文只针对Vue3前端所编写的双Token刷新解决方案,关于Spring Cloud微服务项目的双Token刷新实现,请参考:Spring Cloud + JWT实现双Token刷新
  2. 关于Vue3项目的搭建,请参考:Vite 创建 Vue3 + TS 项目
  3. 本文将通过封装Axios的方式,让前端实现无感刷新Token,关于Axios的封装,请参考:Vue3项目基于Axios封装request请求

刷新机制

在完成上述步骤后,我们就可以开始对前端项目进行操作了。但首先,我们需要了解到双Token刷新的机制:

在使用 Token 认证时,我们通常会使用两种Token:

  1. **Access Token:**用于身份验证,通常时效较短(如 10 分钟)。
  2. Refresh Token:用于获取新的 Access Token,时效较长(如 7 天至几个月)。

Access Token 过期时,我们可以使用Refresh Token 来请求新的Access Token,而不是要求用户重新登录。通过这种方式,用户的体验将更加平滑。

但是,这里是博主自己写的后端,博主的服务端在双Token刷新机制上的原理跟上述是一样的, 不同的是,博主在生成Token的时候,并没有将Refresh Token 返回给前端,而是跟UserId 一起以键值对的形式存储在了Redis中。

在客户端Access Token 过期后,直接根据Base64 解析出Access Token 载荷中的UserId ,然后根据这个UserId 查询存储在Redis 中的Refresh Token ,如果这个Refresh Token 有效且是合法的,那么我们就根据之前Access Token 载荷中的信息重新生成一个Access Token 返回给客户端,以此来达到刷新Token的目的。

根据以上Token 刷新机制,我们在Vue3 前端代码中,可以给出一个无感刷新Token的思路:

  • 如果Access Token 过期,那么我们可以通过Axios 的响应拦截器获取到新的Access Token
  • 如果获取到的这个Access Token存在且不为空,我们可以重新发送原始请求

代码实现

javascript 复制代码
// 添加响应拦截器
service.interceptors.response.use(

	async (response) => {

        // 判断是否有新的Token
		if (response.data.ACCESS_TOKEN) {
            // 将服务端返回的新Token存储到Session中
			Session.set('token', response.data.ACCESS_TOKEN);
			// 重新发送原始请求
            const config = response.config;
            try {
                const newResponse = await service.request(config);
                return newResponse;
            } catch (error) {
                return Promise.reject(error);
            }
		}

		// 对响应数据做点什么
		const res = response.data;
		if (res.code && res.code !== 0) {
			// `token` 过期或者账号已在别处登录
			if (res.code === 401 || res.code === 4001) {
				Session.clear(); // 清除浏览器全部临时缓存
				window.location.href = '/'; // 去登录页
				ElMessageBox.alert('你已被登出,请重新登录', '提示', {})
					.then(() => { })
					.catch(() => { });
				return Promise.reject(service.interceptors.response);
			} else {   // 如果响应中有新的 token,则更新 Session 中的 token

				return res;
			}

		} else {
			return res;
		}
	},
	(error) => {
		// 对响应错误做点什么
		if (error.message.indexOf('timeout') != -1) {
			ElMessage.error('网络超时');
		} else if (error.message == 'Network Error') {
			ElMessage.error('网络连接错误');
		} else {
			if (error.response.data) ElMessage.error(error.response.statusText);
			else ElMessage.error('接口路径找不到');
		}
		return Promise.reject(error);
	}
);

检验真理

如图,当Token过期时,我们访问这个查询接口时,Axios进行了两次接口调用

第一次调用这个查询接口时,我们的Token失效了,拿到了服务端给的新的Token

然后,根据我们之前在Axios响应拦截器中的代码逻辑,它在将这个新的Token存储到Session中后,又重新发送了一次原始请求

相关推荐
东方小月9 小时前
从零开发一个 Coding Agent(四):使用状态机校验大模型事件流
前端·人工智能·后端
想做后端的前端9 小时前
WebGL实现FPS游戏
vue.js·游戏·webgl
Csvn10 小时前
🧩 ESM vs CJS 混用的 7 个「天坑」——从 TypeScript 编译到 Node 与浏览器
前端
Csvn10 小时前
🎯 Web 性能 API 集合:Performance Observer 的 5 个冷门妙用
前端
Csvn10 小时前
深入 React 闭包陷阱:从根源上理解并根治 stale closure
前端
whyfail10 小时前
前端学 Spring Boot(8):接口为什么越用越慢?
前端·spring boot·后端
用户0595401744611 小时前
LangChain 记忆测试踩坑实录:这两个坑让我排查了 4 小时
前端·css
程序员黑豆11 小时前
鸿蒙应用开发:@Monitor 装饰器使用教程
前端·harmonyos
用户9385156350711 小时前
从零构建《天龙八部》知识库:EPUB 加载→文本分割→向量嵌入→Milvus 存储→RAG 问答,一条链路打通
javascript·人工智能·全栈
SamChan9011 小时前
在Web应用中集成PDF多语言翻译功能:PDFTranslator API实战指南
前端·python·ai·pdf·yapi·机器翻译