繁体   English   中英

如何在 React.js 应用程序中刷新 JWT 令牌?

[英]How to refresh JWT tokens in React.js Application?

我在这里检查了所有类似的问题,但没有一个是我需要的。 我正在保护我的应用程序中的路由,并随每个请求发送 JWT,这里一切正常。 问题是当 JWT 到期时,我需要知道如何刷新该令牌并使用户保持登录状态,而不是注销用户。

每个人都在谈论创建一个处理该问题的“中间件”,但没有人说如何创建该中间件以及其中包含什么?

那么,这样做的最佳实践是什么? 我应该在发送任何请求之前检查 JWT 的到期日期吗? 或者我应该等待“401”响应然后尝试刷新令牌(我不知道该怎么做),或者究竟是什么?

如果有人在 Github 上有这样的中间件或包或项目的工作示例可以帮助我解决这个问题,那就太好了。

我只对流程的前端部分感兴趣,从反应发送什么以及我应该收到什么以及如何处理它。

如果您正在使用 Axios(我强烈推荐),您可以在响应的拦截器中声明您的令牌刷新行为。 这将适用于 Axios 发出的所有 https 请求。

这个过程就像

  1. 检查错误状态是否为 401
    • 如果有一个有效的刷新令牌:使用它来获取访问令牌
    • 如果没有有效的刷新令牌:注销用户并返回
  2. 使用新令牌再次重做请求。

下面是一个例子:

axios.interceptors.response.use(
  (response) => {
    return response
  },
  (error) => {
    return new Promise((resolve) => {
      const originalRequest = error.config
      const refreshToken = localStorage.get('refresh_token')
      if (error.response && error.response.status === 401 && error.config && !error.config.__isRetryRequest && refreshToken) {
        originalRequest._retry = true

        const response = fetch(api.refreshToken, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            refresh: refreshToken,
          }),
        })
          .then((res) => res.json())
          .then((res) => {
            localStorage.set(res.access, 'token')

            return axios(originalRequest)
          })
        resolve(response)
      }

      return Promise.reject(error)
    })
  },
)

你的中间件应该看起来像这个代码块(例如,你可以使用任何你想要的)

/* eslint-disable */
import request from 'superagent';
function call(meta, token) {
  const method = meta.API_METHOD ? meta.API_METHOD : 'GET';
  let req = request(method, 'http://localhost:8000/' + meta.API_CALL);
  req = req.set({ Authorization: `JWT ${token}` });
  req = meta.API_TYPE ? req.type('Content-Type', meta.API_TYPE) : req.set('Content-Type', 'application/json');
  if (meta.API_PAYLOAD) {
    req = req.send(meta.API_PAYLOAD);
  }
  if (meta.API_QUERY) {
    req.query(meta.API_QUERY);
  }

  return req;
}

export default store => next => action => {
  const state = store.getState();
  const token = state.logged && state.logged.get('token') ?
    state.logged.get('token') : 'eyJhbGciOiJIUzUxMiJ9';
  if (action.meta && action.meta.API_CALL) {
    call(action.meta, token)
      .then((res) => {
        store.dispatch({
          type: action.meta.API_SUCCESS,
          result: res.body,
        });
      })
      .catch(({ status, response }) => {
        if (action.meta.API_ERRORS && action.meta.API_ERRORS[status]) {
          return store.dispatch({
            type: action.meta.API_ERRORS[status],
            result: response.body,
          });
        }
        if (action.meta.API_ERRORS && action.meta.API_ERRORS[status] === '401') {
          /*call the refresh token api*/
          call(<Your Meta for refreshing>, <expiredtoken>)
                .then((res) => {
                    store.dispatch({
                    type: action.meta.API_SUCCESS,
                    result: res.body,
                    });
                })
                .catch(({ status, response }) => {
                    if (action.meta.API_ERRORS && action.meta.API_ERRORS[status]) {
                    return store.dispatch({
                        type: action.meta.API_ERRORS[status],
                        result: response.body,
                    });
                    }
                    throw response;
                });
        }
        throw response;
      });
  }
  return next(action);
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM