JWT过期后如何自动刷新Token而不让用户重新登录?
我在React项目里用JWT做用户认证,登录后把access_token和refresh_token都存localStorage了。但access_token只有15分钟有效期,过期后接口就401了,总不能让用户手动重新登录吧?试过在拦截器里判断401就调刷新接口,但经常出现多个请求同时触发刷新,导致拿到多个新token甚至覆盖问题。
下面是我现在写的axios拦截器逻辑,感觉哪里不对:
axios.interceptors.response.use(
res => res,
async err => {
if (err.response?.status === 401) {
const { data } = await axios.post('/auth/refresh', {
refreshToken: localStorage.getItem('refresh_token')
});
localStorage.setItem('access_token', data.access_token);
// 重新发起原请求?
return axios(err.config);
}
return Promise.reject(err);
}
);
这里给你一套完整的解决方案,一步一步来说明:
首先,我们定义一个正在刷新的状态变量
isRefreshing和一个队列来保存需要重试的请求:接下来修改你的拦截器逻辑,在401错误时先检查是否已经在刷新中:
原理是这样的:当检测到401错误时,如果已经有刷新正在进行,我们就把当前请求放入队列等待处理。只有第一次遇到401错误时才会实际去调用刷新接口。这样就避免了多次同时刷新的问题。
还要注意一点,在你的登录逻辑里最好也设置这个默认header:
最后提醒一下,别忘了在用户退出登录时清理localStorage和移除这些拦截器。这方案虽然看起来有点复杂,但实际应用中非常可靠,解决了我之前很多项目中的token刷新问题。