web-dev-qa-db-ja.com

React-投稿リクエストを送信する前にJWTが有効かどうかを確認する方法は?

別のnoobの質問。 JWT認証を使用してユーザーをシステムにログインし、トークンを取得してlocalstorageに保存してから、データを保存する投稿リクエスト(基本的には大きなフォーム)を送信しています。問題は、一定の時間(20分程度)後にサーバーがトークンを無効にするため、投稿リクエストの一部が401 statusを返すことです。投稿リクエストを送信する前に確認する方法(および必要に応じてログインプロンプトを表示する方法)フォームを作成するためにredux-formを使用しています。

PS:私はアクションクリエイターなどを使用することになっていることは知っていますが、私はまだ初心者なので、これらのことはあまり得意ではありません。

これが私の認証です:

export function loginUser(creds) {

const data = querystring.stringify({_username: creds.username, _password: creds.password});

let config = {
    method: 'POST',
    headers: { 'Content-Type':'application/x-www-form-urlencoded' },
    body: data
};

return dispatch => {
    // We dispatch requestLogin to kickoff the call to the API
    dispatch(requestLogin(creds));

    return fetch(BASE_URL+'/login_check', config)
        .then(response =>
            response.json().then(user => ({ user, response }))
        ).then(({ user, response }) =>  {
            if (!response.ok) {
                // If there was a problem, we want to
                // dispatch the error condition
                dispatch(loginError(user.message));
                return Promise.reject(user)
            } else {
                // If login was successful, set the token in local storage
                localStorage.setItem('id_token', user.token);
                let token = localStorage.getItem('id_token')
                console.log(token);
                // Dispatch the success action
                dispatch(receiveLogin(user));
            }
        }).catch(err => console.log("Error: ", err))
    }
}

これがPOSTリクエストです(redux-formからvaluesオブジェクトを取得しています)

const token = localStorage.getItem('id_token');
const AuthStr = 'Bearer '.concat(token);

let headers ={
headers: { 'Content-Type':'application/json','Authorization' : AuthStr }
};

export default (async function showResults(values, dispatch) {
axios.post(BASE_URL + '/new', values, headers)
    .then(function (response) {
        console.log(values);
        console.log(response);
    })
    .catch(function (error) {
        console.log(token);
        console.log(values)
        console.log(error.response);
    });
});

P.P.S:私のコードを改善するための提案があれば、コメントしてください。

7
Samia Ruponti

JWTの有効期限は、2つの方法で確認できます。まず最初に、jsonwebtokenパッケージをインストールして、ファイルの先頭にそれを要求する必要があります。その後、以下の方法に従って、残りの要求を送信する前にJWTの有効期限を確認できます。

オプション1

var isExpired = false;
const token = localStorage.getItem('id_token');
var decodedToken=jwt.decode(token, {complete: true});
var dateNow = new Date();

if(decodedToken.exp < dateNow.getTime())
    isExpired = true;

オプション2

const token = localStorage.getItem('id_token');
jwt.verify(token, 'shhhhh', function(err, decoded) {
  if (err) {
    /*
      err = {
        name: 'TokenExpiredError',
        message: 'jwt expired',
        expiredAt: 1408621000
      }
    */
  }
});

そのメソッドのエラーを確認してください。 TokenExpiredErrorの場合、それはトークンが期限切れであることを意味します。

13
Suvethan Nantha

ミドルウェアを使用して、トークンの有効期限が切れているかどうかを確認することもできます。トークンがほとんど期限切れになる場合は、トークンを更新することもできます。たとえば、次のようなことができます。

 export function jwtMiddleware({ dispatch, getState }) {
  return (next) => (action) => {
    switch (action.type) {
      case 'CHECK_AUTH_TOKEN' :
        if (getState().auth && getState().auth.token) {
          var tokenExpiration = jwtDecode(getState().auth.token).exp;
          var tokenExpirationTimeInSeconds = (tokenExpiration - moment(Math.floor(Date.now() / 1000)));
          if (tokenExpiration && tokenExpirationTimeInSeconds < 20) {
            history.Push(i18next.t('translation:routes.auth.logout'));
          }
        }
      break;
      case 'UPDATE_AUTH_TOKEN' :
        if (getState().auth && getState().auth.token) {
          var tokenExpiration = jwtDecode(getState().auth.token).exp;
          var tokenExpirationTimeInSeconds = (tokenExpiration - moment(Math.floor(Date.now() / 1000)));
          if (tokenExpiration && tokenExpirationTimeInSeconds < 100 && tokenExpirationTimeInSeconds > 20) {
            if (!getState().auth.fetching) {
              return dispatch(refreshAuthToken(getState().auth));
            }
          }
        }
      break;
      case 'REFRESH_AUTH_TOKEN_FAIL' :
        if (getState().auth && getState().auth.token) {
          return dispatch(removeAuthToken(getState().auth)).then(response => {
            history.Push(i18next.t('translation:routes.auth.logout'));
          });
        }
      break;
      }
    return next(action);
  }
}
2
directory