reactjs - 在 axios 拦截器错误的情况下如何重新调用 API

标签 reactjs axios jwt

我正在使用 JWT 身份验证开发 React 项目并编写此代码。

const service = axios.create({
  baseURL: API_BASE_URL,
  timeout: 60000
});

service.interceptors.response.use( (response) => {
    return response.data
}, async (error) => {

        const originalRequest = error.config;
    
    // Remove token and redirect 
    if (error.response.status === 400 || error.response.status === 403) {
        localStorage.removeItem(AUTH_TOKEN)
        history.push(ENTRY_ROUTE)
        window.location.reload();
    }

    // Unauthorized error token should refresh with access token
    if (error.response.status === 401) {
        const jwtToken = localStorage.getItem(AUTH_TOKEN)
        const token = JSON.parse(jwtToken)
        const refresh_token = token['refresh'];
        const tokenParts = JSON.parse(atob(refresh_token.split('.')[1]));

        // exp date in token is expressed in seconds, while now() returns milliseconds:
        const now = Math.ceil(Date.now() / 1000);
        if (tokenParts.exp > now) {
            try {
                const res = await service.post('/authentication/token/refresh/', {refresh: refresh_token});
                localStorage.setItem(AUTH_TOKEN, JSON.stringify(res));
                service.headers[TOKEN_PAYLOAD_KEY] = "JWT " + res['access'];
                originalRequest.headers[TOKEN_PAYLOAD_KEY] = "JWT " + res['access'];
                return service(originalRequest);
            }
            catch (error) {

            }
        }
        else {
            localStorage.removeItem(AUTH_TOKEN);
            history.push(ENTRY_ROUTE);
            window.location.reload();
        }

    }

    return Promise.reject(error);
});

这运行良好,没有错误,但我有事要问。当 token 过期并调用某些 API 时,我得到 401 状态代码以获取带有刷新 token 的访问 token 。并正确返回访问 token 。

但是没有办法重新调用失败的 API(只是使用expired access token 调用)。这就是为什么在某些情况下我可能没有来自后端的响应(想象一下,用户单击按钮,但没有响应,因此他应该再次单击按钮以查看响应。这是因为使用新的访问 再次标记 )

这个代码在项目的所有部分都用到了,我有很多 API 调用,所以似乎不可能在每个 React 组件中重新调用失败的 API。

我该如何解决这个问题?

最佳答案

最好的办法是使用原始请求(使用新 token )再次调用 axios。我还没有尝试设置 JWT 服务器并执行这个场景,但是像下面这样的东西应该可以工作:

const service = axios.create({
  baseURL: API_BASE_URL,
  timeout: 60000,
});

service.interceptors.response.use(
  (response) => {
    return response.data;
  },
  async (error) => {
    const originalRequest = error.config;

    // Remove token and redirect
    if (error.response.status === 400 || error.response.status === 403) {
      localStorage.removeItem(AUTH_TOKEN);
      history.push(ENTRY_ROUTE);
      window.location.reload();
    }

    if (error.response.status != 401) return Promise.reject(error);

    // Unauthorized error token should refresh with access token
    const jwtToken = localStorage.getItem(AUTH_TOKEN);
    const token = JSON.parse(jwtToken);
    const refresh_token = token["refresh"];
    const tokenParts = JSON.parse(atob(refresh_token.split(".")[1]));

    // exp date in token is expressed in seconds, while now() returns milliseconds:
    const now = Math.ceil(Date.now() / 1000);
    if (tokenParts.exp > now) {
      try {
        const res = await service.post("/authentication/token/refresh/", {
          refresh: refresh_token,
        });
        localStorage.setItem(AUTH_TOKEN, JSON.stringify(res));
        service.headers[TOKEN_PAYLOAD_KEY] = "JWT " + res["access"];
        originalRequest.headers[TOKEN_PAYLOAD_KEY] = "JWT " + res["access"];

        axios
          .request(originalRequest)
          .then((response) => {
            Promise.resolve(response);
          })
          .catch((err) => {
            Promise.reject(err);
          });
        //return service(originalRequest);
      } catch (error) {
        Promise.reject(error);
      }
    } else {
      localStorage.removeItem(AUTH_TOKEN);
      history.push(ENTRY_ROUTE);
      window.location.reload();
      Promise.reject(error);
    }
  }
);

希望对您有所帮助👍

关于reactjs - 在 axios 拦截器错误的情况下如何重新调用 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72998550/

相关文章:

json - JWT 是否共享/存储用于在客户端和服务器上签名的 secret ?

reactjs - react SPA中的魔术链接身份验证

python - 如何解决错误 405 方法不允许,对于 django graphql 服务器和前端 react axios

javascript - 如何将 map() 与来自 axios 响应的数据一起使用?

javascript - 渲染函数不渲染任何东西 React Native

php - Postman 工作时,Guzzle POST 请求 JWT API 未经授权

javascript - React 访问渲染函数之外的组件

javascript - 无法分配给对象的只读属性

javascript - 如何更改react-bootstrap导航栏链接的悬停效果?

types - 使用JwtSessionHandler时键入错误-dart