Axios Token刷新拦截器问题:浏览器加载停滞且Cookie不生效
Axios拦截器刷新Token问题排查
Cookie不显示的常见原因及解决
- 跨域配置遗漏:跨域场景下,服务器返回
Set-Cookie时必须指定SameSite=None; Secure(HTTPS环境),同时前端所有请求(包括刷新Token的请求)要开启withCredentials: true,否则浏览器会拒绝保存Cookie。 - Cookie属性限制:如果Cookie设置了
HttpOnly,浏览器控制台的Application面板里看不到这个Cookie,但它会正常在请求中携带;如果是HTTP环境下设置了Secure属性,浏览器也不会存储该Cookie。 - Axios配置缺失:刷新Token的请求没有开启
withCredentials,导致服务器返回的Cookie无法被浏览器保存。
请求停滞的常见原因及解决
- 拦截器死循环:刷新Token的请求被自身拦截器重复拦截,导致无限循环。解决方法是在拦截器中排除刷新Token的请求路径,或者给原请求标记
_retry属性避免重复处理。 - Refresh Token过期未处理:如果Refresh Token也已过期,服务器返回错误,但拦截器没有捕获这个错误并终止流程,导致请求一直pending。需要在刷新失败时直接跳转到登录页,终止后续逻辑。
- 异步逻辑错误:拦截器中刷新Token的异步操作没有正确返回Promise,或者没有处理resolve/reject,导致原请求一直等待。确保刷新请求返回Promise,并在成功后重新发起原请求,失败时抛出错误。
修正后的拦截器示例代码
// 请求拦截器 axios.interceptors.request.use( config => { // 排除刷新Token的请求,避免被拦截 if (config.url !== '/api/refresh-token') { const token = localStorage.getItem('accessToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } } return config; }, error => Promise.reject(error) ); // 响应拦截器 axios.interceptors.response.use( response => response, async error => { const originalRequest = error.config; // 只处理一次401,防止死循环 if (error.response.status === 401 && !originalRequest._retry) { originalRequest._retry = true; try { // 刷新请求必须开启withCredentials const refreshRes = await axios.post('/api/refresh-token', {}, { withCredentials: true }); const newToken = refreshRes.data.accessToken; localStorage.setItem('accessToken', newToken); // 重新设置请求头并发起原请求 originalRequest.headers.Authorization = `Bearer ${newToken}`; return axios(originalRequest); } catch (refreshErr) { // 刷新失败,直接跳登录 window.location.href = '/login'; return Promise.reject(refreshErr); } } return Promise.reject(error); } );
服务器端Set-Cookie配置示例
确保返回的Cookie包含必要属性:
Set-Cookie: refreshToken=your-refresh-token; Path=/; Domain=your-domain.com; SameSite=None; Secure; HttpOnly
内容的提问来源于stack exchange,提问作者Murugesan
相关产品推荐
相关产品推荐

