在 Vue 项目中实现无感 Token 刷新在前端项目中,Token 通常用于用户认证和权限管理。无论是基于 JWT (
在前端项目中,Token 通常用于用户认证和权限管理。无论是基于 JWT (JSON Web Token) 还是其他类型的 Token,它们往往有一个过期时间。当 Token 过期时,用户的操作会受到影响,因此我们需要一种无感知(或“静默”)的方式来刷新 Token,确保用户在会话中的操作不会中断。
本文将介绍如何在 Vue 项目中实现 Token 的无感刷新,包括 Token 刷新的原理、拦截器的应用以及如何处理 Token 过期。
一、Token 刷新的背景
通常,Token 分为两种:
- 访问令牌 (Access Token):用于每次请求时验证用户身份,通常有效期较短。
- 刷新令牌 (Refresh Token):用于刷新访问令牌,当访问令牌过期时,可以使用刷新令牌获取新的访问令牌。
在实际应用中,访问令牌的有效期较短,主要是为了安全性。当访问令牌过期时,我们不想强制用户重新登录,而是通过刷新令牌来获取新的访问令牌,从而实现无感刷新。
二、无感 Token 刷新的实现原理
无感刷新是指在用户不感知的情况下,当 Token 过期时自动刷新并重新发起请求。这个过程通常包含以下步骤:
- 每次发起请求时,检查访问令牌的有效性。
- 如果访问令牌过期,暂停当前请求并使用刷新令牌获取新的访问令牌。
- 使用新的访问令牌重新发起之前被暂停的请求。
- 更新应用中的 Token 信息。
三、在 Vue 项目中实现 Token 无感刷新
在 Vue 项目中,我们通常使用 Axios 来处理 HTTP 请求。为了实现无感刷新,我们可以使用 Axios 的拦截器来拦截请求和响应,检测 Token 是否过期,并在需要时自动刷新。
1. 配置 Axios 拦截器
首先,我们需要设置 Axios 的请求和响应拦截器:
import axios from 'axios';
import store from '@/store'; // 假设我们将 token 保存在 Vuex 中
import router from '@/router';
const apiClient = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL,
timeout: 10000
});
// 请求拦截器,携带 token
apiClient.interceptors.request.use(
config => {
const accessToken = store.getters['auth/accessToken'];
if (accessToken) {
config.headers['Authorization'] = `Bearer ${accessToken}`;
}
return config;
},
error => {
return Promise.reject(error);
}
);
// 响应拦截器,检查 token 是否过期
apiClient.interceptors.response.use(
response => {
return response;
},
async error => {
const originalRequest = error.config;
const refreshToken = store.getters['auth/refreshToken'];
// 检查是否是认证错误(如 401)
if (error.response.status === 401 && !originalRequest._retry && refreshToken) {
originalRequest._retry = true;
// 尝试使用刷新令牌获取新的访问令牌
try {
const response = await axios.post('/auth/refresh', { token: refreshToken });
const newAccessToken = response.data.accessToken;
// 更新存储中的 token
store.commit('auth/SET_ACCESS_TOKEN', newAccessToken);
// 重新发起之前失败的请求
originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`;
return apiClient(originalRequest);
} catch (refreshError) {
// 刷新失败,跳转到登录页面
store.commit('auth/LOGOUT');
router.push('/login');
}
}
return Promise.reject(error);
}
);
export default apiClient;
2. 关键点解析
-
请求拦截器:在每次请求发送前,检查
accessToken
是否存在,并将其添加到请求头的Authorization
字段中,确保后端可以识别用户身份。 -
响应拦截器:如果响应状态码为
401
,说明访问令牌无效或过期。此时,会尝试使用refreshToken
请求新的accessToken
。成功后,更新store
中的accessToken
并重新发起之前失败的请求。
3. Vuex 管理 Token
为了更好地管理 Token,我们可以使用 Vuex 来存储和更新 Token 信息。
// store/modules/auth.js
const state = {
accessToken: localStorage.getItem('accessToken') || '',
refreshToken: localStorage.getItem('refreshToken') || ''
};
const getters = {
accessToken: state => state.accessToken,
refreshToken: state => state.refreshToken
};
const mutations = {
SET_ACCESS_TOKEN(state, token) {
state.accessToken = token;
localStorage.setItem('accessToken', token);
},
SET_REFRESH_TOKEN(state, token) {
state.refreshToken = token;
localStorage.setItem('refreshToken', token);
},
LOGOUT(state) {
state.accessToken = '';
state.refreshToken = '';
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
}
};
export default {
state,
getters,
mutations
};
在 Vuex 中,我们使用 localStorage
来持久化 accessToken
和 refreshToken
,这样即使用户刷新页面,Token 也不会丢失。
四、自动刷新和用户体验
Token 无感刷新极大地提升了用户体验,因为用户在 Token 过期时无需重新登录。但需要注意以下几点:
- 安全性:刷新令牌的有效期应比访问令牌长,且只能使用一次,防止滥用。
- 定时刷新:可以在前端设置一个定时器,在 Token 过期前自动刷新,而不是等到请求 401 错误时才刷新。
- 用户操作:在刷新令牌也过期时,需要引导用户重新登录。
五、总结
在 Vue 项目中实现无感 Token 刷新,可以确保用户在 Token 过期时不会被强制登出或中断操作。通过 Axios 拦截器和 Vuex 的结合,我们可以实现自动化的 Token 管理和刷新流程。这不仅提升了安全性,也为用户提供了更加流畅的使用体验。
希望本文能帮助你在 Vue 项目中实现 Token 无感刷新。
转载自:https://juejin.cn/post/7411124991884001330