多个请求的 axios 拦截器刷新令牌

Posted

技术标签:

【中文标题】多个请求的 axios 拦截器刷新令牌【英文标题】:Axios interceptor refresh token for multiple requests 【发布时间】:2020-01-13 09:13:30 【问题描述】:

我将抛​​出http请求,因为我在返回401时调用了刷新令牌。刷新令牌响应后,我需要抛出之前的请求

示例 登录 -> — 1 小时后— —> 调用产品 —> 401 —> 调用刷新令牌 —> 调用产品

我尝试这个链接a link 并查看这个链接a link 但不起作用。

捕捉 401 错误

setInterceptors = () => 
        axios.interceptors.response.use(
            response => 
                return response;
            ,
            err => 
                return new Promise((resolve, reject) => 
                    if (err.response.status === 401 && err.config && !err.config.__isRetryRequest) 

                        const originalRequest = err.config;

                        this.emit('onAutoLogin', originalRequest);
                    
                    // throw err;
                );
            
        );
    ;

调用我的操作

jwtService.on('onAutoLogin', originalRequest => 
                    jwtService
                        .signInWithToken()
                        .then(res => 
                            if (res.access_token) 
                                originalRequest.headers['Authorization'] = 'Bearer ' + res.access_token;


Axios.request(originalRequest).then(response => 
                                    store.dispatch(
                                        type: ** MY PROBLEM İS HERE **
                                        payload: response.data
                                    );
                                );
                            
                        )
                        .catch(err => 
                            jwtService.setSession(null); 
);

【问题讨论】:

除了“它不起作用”之外,您能否更具体地说明问题所在?有错误吗?它只是不调度动作吗?操作是否已分派但未处理?你在调试中尝试过什么? 你的 originalRequest 真的是整个 err.config 对象吗?或者你的意思是解构它? 刷新令牌正在工作。 originalRequest 实际上是整个 err.config 对象。我还用 originalRequest 调用了最后一个 http 操作。但我无法保存触发返回数据所需的操作(类型、有效负载)。 是的,我在type 所在的行上看到了一条评论。问题是什么?目前尚不清楚“无法控制行动……”是什么意思。 我无法在 Redux 中获取最后一个操作。 【参考方案1】:

使用this link我能够在不触发redux store的情况下解决问题。

let isRefreshing = false;
 let failedQueue = [];

       const processQueue = (error, token = null) => 
            failedQueue.forEach(prom => 
                if (error) 
                    prom.reject(error);
                 else 
                    prom.resolve(token);
                
            );

            failedQueue = [];
        ;

axios.interceptors.response.use(
            response => 
                return response;
            ,
err => 
                const originalRequest = err.config;

                if (err.response.status === 401 && !originalRequest._retry) 
                    if (isRefreshing) 
                        return new Promise(function(resolve, reject) 
                            failedQueue.push( resolve, reject );
                        )
                            .then(token => 
                                originalRequest.headers['Authorization'] = 'Bearer ' + token;
                                return axios(originalRequest);
                            )
                            .catch(err => 
                                return Promise.reject(err);
                            );
                    

                    originalRequest._retry = true;
                    isRefreshing = true;

                    return new Promise(function(resolve, reject) 
                        axios
                            .post('/fooUrl/refreshToken', 
                                refreshToken: "fooToken")
                            .then(( data ) => 
                                axios.defaults.headers.common['Authorization'] = 'Bearer ' + data.fooToken;
                                originalRequest.headers['Authorization'] = 'Bearer ' + data.fooToken;
                                processQueue(null, data.fooToken);
                                resolve(axios(originalRequest));
                            )
                            .catch(err => 
                                processQueue(err, null);
                                store.dispatch(showMessage( message: 'Expired Token' ));

                                reject(err);
                            )
                            .then(() => 
                                isRefreshing = false;
                            );
                    );
                

                return Promise.reject(err);
            
        );

【讨论】:

好人,谢谢 :)

以上是关于多个请求的 axios 拦截器刷新令牌的主要内容,如果未能解决你的问题,请参考以下文章

Axios 拦截器不会在页面加载时拦截

如何让 axios 拦截器重试原始请求?

用于令牌刷新的 axios 全局拦截器

在 React 中无效时自动刷新令牌

如何在 axios 拦截器中设置 http cookie?

Axios 中的单元测试拦截器逻辑