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中后,又重新发送了一次原始请求

相关推荐
naildingding5 分钟前
3-ts接口 Interface
前端·typescript
mONESY5 分钟前
JavaScript 栈、队列、数组与链表核心知识点总结
javascript·面试
小小前端仔LC12 分钟前
Node.js + LangChain + React:搭建个人知识库(六)- “吃什么”项目实战:从700+菜谱入库到Taro H5端JSON渲染
前端·后端
ZengLiangYi12 分钟前
TypeScript 项目配置:tsconfig、ESM、路径别名
javascript·typescript·aigc
晓131328 分钟前
【Cocos Creator 3.x】篇——第二章 入门
前端·javascript·游戏引擎
想要成为糕糕手32 分钟前
前端必修课:JavaScript 数组与数据结构底层逻辑全解析
javascript·数据结构·面试
程序员黑豆37 分钟前
AI全栈开发之Java:怎么配置Java环境变量
前端·后端·ai编程
xiaofeichaichai1 小时前
React Hooks
前端·javascript·react.js
数据知道1 小时前
C++ 层拦截:修改 Blink 引擎与 V8 绑定的底层逻辑
javascript·数据采集·指纹浏览器·风控
问心无愧05131 小时前
ctf show web入门110
前端·笔记