前端双 Token 无感刷新详解
在现代的 web 开发中,用户体验和安全性始终是开发者关注的重点。无感刷新通过双 Token(Access Token 和 Refresh Token)的方案,实现了在用户使用过程中无需频繁登陆的良好体验。本文将详细介绍双 Token 的机制,以及如何在前端实现无感刷新。
1. 双 Token 机制简介
双 Token 机制通常分为 Access Token 和 Refresh Token:
-
Access Token:用于访问受保护资源的令牌,通常有效期较短(例如 15 分钟)。每次用户需要进行 API 请求时,都需要提供 Access Token。
-
Refresh Token:用于获取新的 Access Token,通常有效期较长(例如 7 天或 30 天)。当 Access Token 过期时,可以使用 Refresh Token 来获取新的 Access Token。
这种机制的好处在于,即使 Access Token 被盗,也因其短暂的有效期降低了风险。同时,通过 Refresh Token,用户无需频繁登录,也提供了较为流畅的用户体验。
2. 如何实现双 Token 无感刷新
在前端实现双 Token 无感刷新,主要分为以下几个步骤:
-
登录时获取 Token:用户输入用户名和密码进行登录,服务器验证后返回 Access Token 和 Refresh Token。
-
存储 Token:将获取的两个 Token 存储在浏览器的 localStorage 或 sessionStorage 中(注意,Refresh Token 应该尽量避免暴露)。
-
使用 Access Token 访问 API:每次需要访问 API 时,将 Access Token 附加到请求头中。
-
处理 Access Token 过期:在前端判断 Access Token 是否过期,如果过期,使用 Refresh Token 请求新的 Access Token。
-
更新 Token:将新的 Access Token 更新到浏览器存储中。
3. 代码示例
以下是一个简单的前端双 Token 无感刷新示例代码,假设使用的是 axios 作为 HTTP 请求库。
import axios from 'axios';
// 登录函数
async function login(username, password) {
const response = await axios.post('/api/login', { username, password });
// 假设返回的数据中有 accessToken 和 refreshToken
const { accessToken, refreshToken } = response.data;
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', refreshToken);
}
// 请求拦截器
axios.interceptors.request.use(async (config) => {
const accessToken = localStorage.getItem('accessToken');
// 将 accessToken 添加到请求头中
if (accessToken) {
config.headers['Authorization'] = `Bearer ${accessToken}`;
}
return config;
}, (error) => {
return Promise.reject(error);
});
// 响应拦截器
axios.interceptors.response.use(response => {
return response;
}, async (error) => {
const originalRequest = error.config;
// 检查是否因为 accessToken 过期而导致的错误
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true; // 避免递归调用
const refreshToken = localStorage.getItem('refreshToken');
try {
const response = await axios.post('/api/refresh', { refreshToken });
const { accessToken } = response.data;
// 更新 Access Token
localStorage.setItem('accessToken', accessToken);
// 重新设置请求头并重试原请求
originalRequest.headers['Authorization'] = `Bearer ${accessToken}`;
return axios(originalRequest);
} catch (refreshError) {
// 如果刷新失败,清除 Token,并跳转到登录页
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
window.location.href = '/login';
}
}
return Promise.reject(error);
});
// 示例调用 API
async function getUserData() {
try {
const response = await axios.get('/api/user');
console.log(response.data);
} catch (error) {
console.error('请求失败:', error);
}
}
4. 总结
使用双 Token 机制进行无感刷新是一种有效的方法,可以在保证安全性的同时提高用户体验。在实现过程中,我们可以利用 HTTP 请求拦截器,轻松处理 Access Token 的过期和刷新。通过这样的方式,用户在使用应用时,可以感受到流畅的操作体验,而无需重复登录,提高了整体的使用满意度。