如何修改Axios请求配置?解决刷新token后重发请求带旧token问题
问题描述
我向后端发起的每个请求都会携带access token,当token验证不通过时,我会保存原请求配置并发起刷新token的请求。若刷新成功,我会重发原请求,但此时原请求仍携带旧token。请问如何更新headers.Authorization中的值?
现有代码
import axios from 'axios' import { setAccessToken } from '../store/authSlice' export const axiosConfig = (accessToken: any, dispatch: any) => { const API_URL = 'http://localhost:3001/api' const $api = axios.create({ withCredentials: false, baseURL: API_URL }) $api.interceptors.request.use((config) => { config.headers!.Authorization = `Bearer ${accessToken}` return config }) $api.interceptors.response.use( (config) => { return config }, async (error) => { const originalRequest = error.config if (error.response.status === 403 && error.config && !error.config._isRetry) { originalRequest._isRetry = true try { const response = await axios.get(`${API_URL}/auth/refresh-tokens`, { withCredentials: false, headers: { Authorization: `Bearer ${localStorage.refreshToken}` } }) localStorage.setItem('refreshToken', response.data.refreshToken) dispatch(setAccessToken(response.data.accessToken)) // new token return $api.request(originalRequest) // <=== original request with old token } catch (e) { console.log('error') } } throw error } ) return $api }
解决方案
核心问题有两个:一是直接复用的originalRequest保留了旧token的headers;二是请求拦截器依赖传入的accessToken参数,这个参数不会自动同步最新值。可以按以下方式修改:
关键修改点
- 实时获取最新token:请求拦截器不再用传入的固定参数,而是从localStorage或store实时取最新的accessToken,确保后续请求自动使用新token。
- 更新原请求的headers:刷新token成功后,直接修改
originalRequest的Authorization头,替换成新token再重发。
修改后的代码:
import axios from 'axios' import { setAccessToken } from '../store/authSlice' export const axiosConfig = (dispatch: any) => { const API_URL = 'http://localhost:3001/api' const $api = axios.create({ withCredentials: false, baseURL: API_URL }) $api.interceptors.request.use((config) => { // 每次请求都从localStorage拿最新的accessToken const accessToken = localStorage.getItem('accessToken') if (accessToken) { config.headers!.Authorization = `Bearer ${accessToken}` } return config }) $api.interceptors.response.use( (config) => { return config }, async (error) => { const originalRequest = error.config if (error.response.status === 403 && error.config && !error.config._isRetry) { originalRequest._isRetry = true try { const response = await axios.get(`${API_URL}/auth/refresh-tokens`, { withCredentials: false, headers: { Authorization: `Bearer ${localStorage.refreshToken}` } }) const newAccessToken = response.data.accessToken localStorage.setItem('refreshToken', response.data.refreshToken) localStorage.setItem('accessToken', newAccessToken) // 把新token存到localStorage dispatch(setAccessToken(newAccessToken)) // 直接更新原请求的Authorization头 originalRequest.headers!.Authorization = `Bearer ${newAccessToken}` return $api.request(originalRequest) } catch (e) { console.log('登录已过期,请重新登录') } } throw error } ) return $api }
说明
- 移除了固定的
accessToken参数,请求拦截器实时获取最新token,避免后续请求还使用旧值。 - 刷新成功后,同步更新localStorage和store的token,同时修改原请求的headers,确保重发请求携带新token。
_isRetry标记避免了403错误时的无限循环请求。
内容的提问来源于stack exchange,提问作者Vladislav
相关产品推荐
相关产品推荐

