如何使用 Redux 刷新 JWT 令牌? [英] How to use Redux to refresh JWT token?

查看:20
本文介绍了如何使用 Redux 刷新 JWT 令牌?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的 React Native Redux 应用使用 JWT 令牌进行身份验证.有许多操作需要此类令牌,​​并且其中很多是同时调度的,例如应用加载时.

Our React Native Redux app uses JWT tokens for authentication. There are many actions that require such tokens and a lot of them are dispatched simultaneously e.g. when app loads.

例如

componentDidMount() {
    dispath(loadProfile());
    dispatch(loadAssets());
    ...
}

loadProfileloadAssets 都需要 JWT.我们将令牌保存在状态和 AsyncStorage 中.我的问题是如何处理令牌过期.

Both loadProfile and loadAssets require JWT. We save the token in the state and AsyncStorage. My question is how to handle token expiration.

本来我打算使用中间件来处理令牌过期

Originally I was going to use middleware for handling token expiration

// jwt-middleware.js

export function refreshJWTToken({ dispatch, getState }) {

  return (next) => (action) => {
    if (isExpired(getState().auth.token)) {
      return dispatch(refreshToken())
          .then(() => next(action))
          .catch(e => console.log('error refreshing token', e));
    }
    return next(action);
};

}

我遇到的问题是 loadProfileloadAssets 操作都会刷新令牌,因为在分派时令牌将过期.理想情况下,我想暂停"需要身份验证的操作,直到刷新令牌.有没有办法用中间件做到这一点?

The problem that I ran into was that refreshing of the token will happen for both loadProfile and loadAssets actions because at the time when they are dispatch the token will be expired. Ideally I would like to "pause" actions that require authentication until the token is refreshed. Is there a way to do that with middleware?

推荐答案

我找到了解决这个问题的方法.我不确定这是否是最佳实践方法,可能还有一些可以改进的地方.

I found a way to solve this. I am not sure if this is best practice approach and there are probably some improvements that could be made to it.

我原来的想法保持不变:JWT 刷新在中间件中.如果使用 thunk,中间件必须在 thunk 之前.

My original idea stays: JWT refresh is in the middleware. That middleware has to come before thunk if thunk is used.

...
const createStoreWithMiddleware = applyMiddleware(jwt, thunk)(createStore);

然后在中间件代码中,我们在任何异步操作之前检查令牌是否已过期.如果它已过期,我们还会检查我们是否已经在刷新令牌——为了能够进行这样的检查,我们向状态添加了对新鲜令牌的承诺.

Then in the middleware code we check to see if token is expired before any async action. If it is expired we also check if we are already are refreshing the token -- to be able to have such check we add promise for fresh token to the state.

import { refreshToken } from '../actions/auth';

export function jwt({ dispatch, getState }) {

    return (next) => (action) => {

        // only worry about expiring token for async actions
        if (typeof action === 'function') {

            if (getState().auth && getState().auth.token) {

                // decode jwt so that we know if and when it expires
                var tokenExpiration = jwtDecode(getState().auth.token).<your field for expiration>;

                if (tokenExpiration && (moment(tokenExpiration) - moment(Date.now()) < 5000)) {

                    // make sure we are not already refreshing the token
                    if (!getState().auth.freshTokenPromise) {
                        return refreshToken(dispatch).then(() => next(action));
                    } else {
                        return getState().auth.freshTokenPromise.then(() => next(action));
                    }
                }
            }
        }
        return next(action);
    };
}

最重要的部分是refreshToken 函数.该函数需要在令牌刷新时分派操作,以便状态将包含对新令牌的承诺.这样,如果我们分派多个同时使用令牌身份验证的异步操作,令牌只会刷新一次.

The most important part is refreshToken function. That function needs to dispatch action when token is being refreshed so that the state will contain the promise for the fresh token. That way if we dispatch multiple async actions that use token auth simultaneously the token gets refreshed only once.

export function refreshToken(dispatch) {

    var freshTokenPromise = fetchJWTToken()
        .then(t => {
            dispatch({
                type: DONE_REFRESHING_TOKEN
            });

            dispatch(saveAppToken(t.token));

            return t.token ? Promise.resolve(t.token) : Promise.reject({
                message: 'could not refresh token'
            });
        })
        .catch(e => {

            console.log('error refreshing token', e);

            dispatch({
                type: DONE_REFRESHING_TOKEN
            });
            return Promise.reject(e);
        });



    dispatch({
        type: REFRESHING_TOKEN,

        // we want to keep track of token promise in the state so that we don't try to refresh
        // the token again while refreshing is in process
        freshTokenPromise
    });

    return freshTokenPromise;
}

我意识到这很复杂.我也有点担心在 refreshToken 中分派动作,这本身不是动作.请告诉我您知道的任何其他使用 redux 处理过期 JWT 令牌的方法.

I realize that this is pretty complicated. I am also a bit worried about dispatching actions in refreshToken which is not an action itself. Please let me know of any other approach you know that handles expiring JWT token with redux.

这篇关于如何使用 Redux 刷新 JWT 令牌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆