在前端开发中,用户的身份验证和会话管理是一个重要的部分。通常情况下,我们使用 JWT(JSON Web Token)来实现用户的身份验证,JWT 在用户登录后会生成一个 token,并将其存储在客户端(如 LocalStorage 或 Cookie)中。然而,token 有一定的有效期,这就需要在 token 过期后进行刷新,以防用户再次登录。
无感刷新是指在用户未察觉的情况下,自动刷新 token,确保用户能够无缝地继续使用应用而不会受到身份验证的影响。在这篇文章中,我们将探讨如何在前端实现无感刷新,包括代码示例和最佳实践。
1. 实现思路
通常,token 刷新的流程如下:
- 用户登录后,后端生成 access token 和 refresh token。
- access token 有短期有效性(例如 15 分钟),而 refresh token 则具有较长的有效性(例如 7 天)。
- 在前端每次请求时,检查 access token 是否即将过期(例如,5 分钟前)。
- 如果即将过期,使用 refresh token 请求新的 access token。
- 更新本地存储中的 access token,并继续后续请求。
2. 代码示例
下面是一个简单的 Vue.js 应用示例,演示如何在应用中实现无感刷新功能。
安装依赖
首先,确保您已安装 Axios(用于发送 HTTP 请求):
npm install axios
创建 Token 管理模块
我们可以创建一个 tokenService.js
模块来管理 token 的获取和刷新。
// tokenService.js
import axios from 'axios';
let accessToken = null;
let refreshToken = null;
// 设置 token
export const setTokens = (newAccessToken, newRefreshToken) => {
accessToken = newAccessToken;
refreshToken = newRefreshToken;
// 将 token 存储到 localStorage
localStorage.setItem('access_token', accessToken);
localStorage.setItem('refresh_token', refreshToken);
};
// 获取 access token
export const getAccessToken = () => {
if (!accessToken) {
accessToken = localStorage.getItem('access_token');
}
return accessToken;
};
// 刷新 access token
export const refreshAccessToken = async () => {
const response = await axios.post('/api/refresh', {
refresh_token: refreshToken,
});
if (response.data && response.data.access_token) {
setTokens(response.data.access_token, response.data.refresh_token);
}
};
// 添加请求拦截器
axios.interceptors.request.use(async (config) => {
const token = getAccessToken();
const expiryTime = decodeJwt(token).exp * 1000;
const currentTime = Date.now();
// 检查 token 是否即将过期
if (expiryTime - currentTime < 5 * 60 * 1000) {
// 如果即将过期,刷新 token
await refreshAccessToken();
}
config.headers.Authorization = `Bearer ${getAccessToken()}`;
return config;
}, error => {
return Promise.reject(error);
});
// 解码 JWT
const decodeJwt = (token) => {
if (!token) return {};
const payload = token.split('.')[1];
return JSON.parse(atob(payload));
};
3. 使用 Token 管理模块
在应用中,只需在用户登录时调用 setTokens
方法设置 token,之后所有的请求都会自动使用拦截器进行 token 的管理。
// 在用户登录时
import { setTokens } from './tokenService';
const loginUser = async (username, password) => {
const response = await axios.post('/api/login', { username, password });
if (response.data) {
setTokens(response.data.access_token, response.data.refresh_token);
}
};
// 在组件中发起请求
const fetchData = async () => {
const response = await axios.get('/api/data');
console.log(response.data);
};
4. 结论
无感刷新机制可以极大地提高用户体验,用户不会因为 token 过期而被迫重新登录。本文中介绍的代码示例展示了如何在前端利用 Axios 拦截器和 token 管理模块实现这一功能。在实际开发中,需注意将 token 存储在安全的位置,并遵循最佳安全实践,以防止 XSS 攻击等安全隐患。