簡體   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