【问题标题】:Axios Interceptor Response Token Refresh API called but getting Token is expired regardless in refreshToken API & lator all APIs调用 Axios 拦截器响应令牌刷新 API 但获取令牌已过期,无论在 refreshToken API 和 lator 中所有 API
【发布时间】:2020-03-13 11:59:52
【问题描述】:

我的 axios 拦截器是:-

axios.interceptors.response.use((response, error) => {
  const originalRequest = response.config;

  if (response.data.status === 'Token is Expired' && originalRequest.url === '/api/refresh') {
    this.props.history.push('/logout');
    Promise.reject(error);
  }

  if (response.data.status === 'Token is Expired' && !originalRequest._retry) {
    originalRequest._retry = true;
    const playerToken = localStorage.getItem('accessToken');
    return axios
      .get('/api/refresh', {
        headers: {
          Authorization: `bearer ${playerToken}`,
        },
      })
      .then(res => {
        console.log('from refreshtoken', res);
        const stringRes = JSON.stringify(res);
        const parsedRes = JSON.parse(stringRes);
        const stringData = JSON.stringify(parsedRes.data);
        const parsedData = JSON.parse(stringData);
        const stringToken = JSON.stringify(parsedData.data);
        const parsedToken = JSON.parse(stringToken);

        if (parsedData.success == true) {
          localStorage.setItem('accessToken', playerToken);
          axios.response.config.headers['Authorization'] = `bearer ${parsedToken}`;
          return Promise.resolve();

          return axios(originalRequest);
        } else {
          this.props.history.push('/logout');
        }
      })
      .catch(err => {
        console.log('from refreshtoken', err);
      });
  }

  return Promise.reject(error);
});

我的代码正在运行,但是当我第一次调用我的刷新令牌 API 时,它还会返回相同的状态“令牌已过期”,因此我已从应用程序中注销。这仅在拦截器中发生。当我在拦截器之外调用 Refresh API 时,它会返回一个刷新令牌。

我的代码有错误吗?或者完全是其他一些编码错误。 请回答并告诉我正确的方法以及我在哪里放置拦截器? 目前它被放置在一个组件中,该组件在登录后被调用。

【问题讨论】:

  • 错误类型:localStorage.setItem('accessToken', parsedToken);

标签: reactjs axios interceptor refresh-token


【解决方案1】:

通常流程应该是这样的:

  1. 定期向accessToken 提出请求
  2. 请求失败,状态码为 401
  3. axios 拦截器捕获它并向token/refresh 发出请求。从该响应中,它会获得一个新的访问令牌。
  4. 重试原始请求。

所以代码应该是这样的(这是我的应用程序中的一个工作示例):

function isUnAuthorizedError(error) {
  return error.config && error.response && error.response.status === 401;
}

function shouldRetry(config) {
  return config.retries.count < 3;
}

function updateAuthToken(response) {
  localStorage.setItem('token', response.data.accessToken);
}

async function authInterceptor(error) {
  error.config.retries = error.config.retries || {
    count: 0,
  };

  if (isUnAuthorizedError(error) && shouldRetry(error.config)) {
    const response = await axios.post(`/token/refresh`, {});

    updateAuthToken(response);

    error.config.retries.count += 1;
    axios.defaults.headers.common.Authorization = `Bearer ${response.data.accessToken}`; // update the accessToken
    return axios.rawRequest(error.config); // retries the original request
  }
  return Promise.reject(error);
}

axios.interceptors.response.use(null, authInterceptor); // This indicates that authInterceptor will work only on request errors (status code >= 400)

希望这个流程更有意义。

【讨论】:

  • 谢谢。我已经做到了。仍然得到相同的响应。
  • 谢谢。我已经理解了你的代码。我试图做同样的事情。将尝试以这种方式实施。让我们看看我会得到什么回应。
  • 另外你能告诉我你把这段代码放在你的应用程序的什么地方吗?我是 axios 拦截器的新手,从我收集到的信息来看,你必须在你的应用程序中调用它们一次,它会在整个应用程序中工作。但是一旦我刷新页面,我的拦截器就会停止工作?
  • 正确,每次页面刷新都要配置拦截器。您可以创建一个文件,在其中创建一个新的 axios 实例并导出该实例。您的所有应用程序都将直接使用此实例而不是 lib。在那里你可以配置你的拦截器和 api 的基本 url 等等......
  • 问题基本上来自后端,关于刷新令牌到期。感谢您的帮助。
猜你喜欢
  • 2018-06-14
  • 2023-03-06
  • 2021-02-11
  • 2019-08-05
  • 2021-09-01
  • 1970-01-01
  • 2022-11-03
  • 2012-02-15
  • 1970-01-01
相关资源
最近更新 更多