我已经设置了一个拦截器来捕获401错误,以便在访问令牌过期时使用刷新令牌获取新的访问令牌。如果在此期间进行任何其他调用,则它们将排队等待访问令牌验证。
这一切都非常顺利。但是,在使用Axios(originalRequest)处理队列时,最初附加的promises没有被调用。请参见下面的示例。
工作中的拦截器代码:
Axios.interceptors.response.use(
response => response,
(error) => {
const status = error.response ? error.response.status : null
const originalRequest = error.config
if (status === 401) {
if (!store.state.auth.isRefreshing) {
store.dispatch('auth/refresh')
}
const retryOrigReq = store.dispatch('auth/subscribe', token => {
originalRequest.headers['Authorization'] = 'Bearer ' + token
Axios(originalRequest)
})
return retryOrigReq
} else {
return Promise.reject(error)
}
}
)
刷新方法 (使用刷新令牌获取新的访问令牌)
refresh ({ commit }) {
commit(types.REFRESHING, true)
Vue.$http.post('/login/refresh', {
refresh_token: store.getters['auth/refreshToken']
}).then(response => {
if (response.status === 401) {
store.dispatch('auth/reset')
store.dispatch('app/error', 'You have been logged out.')
} else {
commit(types.AUTH, {
access_token: response.data.access_token,
refresh_token: response.data.refresh_token
})
store.dispatch('auth/refreshed', response.data.access_token)
}
}).catch(() => {
store.dispatch('auth/reset')
store.dispatch('app/error', 'You have been logged out.')
})
},
auth/actions模块中的订阅方法:
subscribe ({ commit }, request) {
commit(types.SUBSCRIBEREFRESH, request)
return request
},
除了突变之外:
[SUBSCRIBEREFRESH] (state, request) {
state.refreshSubscribers.push(request)
},
这里是一个示例操作:
Vue.$http.get('/users/' + rootState.auth.user.id + '/tasks').then(response => {
if (response && response.data) {
commit(types.NOTIFICATIONS, response.data || [])
}
})
如果此请求被添加到队列中,那是因为要使用刷新令牌获取新令牌,我想附加原始的 then()。
const retryOrigReq = store.dispatch('auth/subscribe', token => {
originalRequest.headers['Authorization'] = 'Bearer ' + token
// I would like to attache the original .then() as it contained critical functions to be called after the request was completed. Usually mutating a store etc...
Axios(originalRequest).then(//if then present attache here)
})
一旦访问令牌已经被刷新,请求队列将被处理:
refreshed ({ commit }, token) {
commit(types.REFRESHING, false)
store.state.auth.refreshSubscribers.map(cb => cb(token))
commit(types.CLEARSUBSCRIBERS)
},
const retryOrigReq = store.dispatch('auth/subscribe').then(token => { originalRequest.headers['Authorization'] = 'Bearer ' + token; return Axios(originalRequest) });
这样的代码应该可以实现。 - Bergi