一、token刷新并发处理队列
本项目(web-company端)已实现了token刷新并发处理队列,主要体现在 src/api/config.ts:
- 当多个请求因 token 过期同时返回 401 时,只有第一个会真正发起刷新 token 请求,其他请求会被加入
failedQueue队列。 - 刷新成功后,队列中的所有请求会被重新发起,并带上新 token。
- 刷新失败则清除本地认证信息并跳转登录页。
核心代码片段说明:
let isRefreshing = false;
let failedQueue: Array<{ resolve, reject }> = [];
const processQueue = (error, token = null) => {
failedQueue.forEach(({ resolve, reject }) => {
error ? reject(error) : resolve(token);
});
failedQueue = [];
};
instance.interceptors.response.use(
// ...正常响应
async error => {
const originalRequest = error.config;
if (error.response?.status === 401 && !originalRequest._retry) {
if (isRefreshing) {
// 正在刷新,加入队列
return new Promise((resolve, reject) => {
failedQueue.push({ resolve, reject });
}).then(token => {
originalRequest.headers.Authorization = `Bearer ${token}`;
return instance(originalRequest);
});
}
// ...发起刷新逻辑
isRefreshing = true;
// 刷新成功后 processQueue(null, newToken)
// 刷新失败 processQueue(refreshError, null)
isRefreshing = false;
}
return Promise.reject(error);
}
);
这样可以避免并发多次刷新 token,保证请求串行恢复。
二、问题
1. 问:你们项目如何处理token过期后的并发刷新问题?
答:
我们在 web-company 端 axios 封装中实现了 token 刷新并发队列。当多个请求因 token 过期同时返回 401 时,只有第一个会发起刷新 token 请求,其他请求会被加入等待队列。刷新成功后,所有等待的请求会自动带上新 token 重试,避免了并发多次刷新和 token 覆盖问题。
2. 问:token刷新失败后,用户体验如何保证?
答:
如果刷新 token 失败(如 refreshToken 失效),我们会清除本地所有认证信息,并自动跳转到登录页,提示用户重新登录,保证安全性和用户体验。
3. 问:token和refreshToken分别如何管理?为什么要分开?
答:
access token 有较短有效期(如15分钟),用于接口鉴权;refresh token 有较长有效期(如7天),仅用于刷新 access token。两者分开存储,提升安全性,防止 access token 泄露后长期有效。我们通过 TokenManager 工具类统一管理本地存储和清除。
4. 问:如何防止token被劫持后长期使用?
答:
access token 过期后必须用 refresh token 换取新 token,且 refresh token 也有过期时间。后端可实现 refresh token 黑名单机制,用户退出登录时将其失效。前端每次请求都带上最新 token,后端中间件统一校验。
5. 问:你们的token刷新机制对高并发场景有何优化?
答:
我们通过 isRefreshing 标志和 failedQueue 队列,保证同一时刻只会有一个刷新 token 请求,其他并发请求等待刷新结果,刷新成功后批量恢复,避免了高并发下多次无效刷新和 race condition 问题,提升了系统稳定性和性能。