我们的React Native Redux应用程序使用JWT令牌进行身份验证。有许多操作需要此类令牌,并且例如在应用加载时会同时分派许多令牌。
例如
componentDidMount() { dispath(loadProfile()); dispatch(loadAssets()); ... }
双方loadProfile并loadAssets要求JWT。我们将令牌保存在和中AsyncStorage。我的问题是如何处理令牌到期。
loadProfile
loadAssets
AsyncStorage
最初,我将使用中间件来处理令牌到期
// 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); };
}
我遇到的问题是,对于令牌loadProfile和loadAssets操作,都会刷新令牌,因为在分发令牌和令牌时,令牌将过期。理想情况下,我想“暂停”需要身份验证的操作,直到刷新令牌为止。有没有办法用中间件做到这一点?
我找到了解决此问题的方法。我不确定这是否是最佳做法,并且可能会有一些改进。
我最初的想法仍然存在:JWT刷新位于中间件中。thunk如果thunk使用中间件,则必须先使用它。
thunk
... const createStoreWithMiddleware = applyMiddleware(jwt, thunk)(createStore);
然后,在中间件代码中,我们检查令牌是否在任何异步操作之前到期。如果过期,我们还将检查是否已经在刷新令牌- 为了能够进行此类检查,我们向该州添加了对新令牌的承诺。
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功能。该功能需要在刷新令牌时分派操作,以便状态将包含对新令牌的承诺。这样,如果我们调度同时使用令牌认证的多个异步操作,则令牌仅刷新一次。
refreshToken
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令牌的方法。