我是React Native的新手,我遇到的第一个障碍就是当它到期时刷新我的访问令牌。基本实现是存在访问令牌和刷新令牌。访问令牌到期,并且在Authorization标头内发送刷新令牌以刷新访问令牌。基于this SO帖子,我实施了一个中间件,在每个API调用期间检查我们的访问令牌是否即将到期。如果是这样,它将启动一个动作创建者,该动作创建者进行API调用以刷新并确认新的访问令牌。我在这里只显示了刷新调用,以免过度复杂化。
问题是检测到需要刷新的同一中间件也被刷新调用本身击中,这导致无限循环并最终超过调用堆栈大小。我想知道是否有人能够帮助我找到解决方法,或者告诉我我愚蠢并提供更好的整体解决方案。任何指导都非常感谢。谢谢!
function auth({ dispatch, getState }) {
return next => action => {
if (typeof action === 'function') {
// Check expiration of our token
if (tokenIsExpired(getState)) {
console.log('Our access token will expire in less than 30s, refreshing');
// Make sure we are not already refreshing the access token
if (!getState().core.refreshTokenIsLoading) {
return next(dispatch(refreshAccessTokenFlow())).then(() => next(action));
} else {
// Take promise from state and act after it
return getState().core.refreshAccessTokenFlow.then(() => next(action));
}
}
}
return next(action);
}
}
export function refreshAccessTokenFlow() {
return (dispatch) => {
return dispatch(refreshAccessToken())
.then((didRefresh) => {
console.log('refresh access token returned');
return Promise.resolve();
})
.catch(error => {
console.log('refresh access token failed: ' + error);
return Promise.reject(error);
});
}
}
答案 0 :(得分:0)
例如,您可以在需要访问令牌的操作中传递元数据,然后在中间件检查中传递元数据,或者您需要根据该元数据验证令牌。
操作文件
// My Team
export function fetchStuffWithOAuthStart(userId) {
return {
type: USER_FETCH_STUFF_WITHOUT_OAUTH_START,
payload: { userId },
meta: {
oauth: true,
}
};
<强>中间件强>
function auth({ dispatch, getState }) {
return next => action => {
if (typeof action === 'function') {
// Check here or you need to validate the token
if (!action.meta || !action.meta.oauth) {
return next(action);
}
// Check expiration of our token
if (tokenIsExpired(getState)) {
console.log('Our access token will expire in less than 30s, refreshing');
// Make sure we are not already refreshing the access token
if (!getState().core.refreshTokenIsLoading) {
return next(dispatch(refreshAccessTokenFlow())).then(() => next(action));
} else {
// Take promise from state and act after it
return getState().core.refreshAccessTokenFlow.then(() => next(action));
}
}
}
return next(action);
}
}
export function refreshAccessTokenFlow() {
return (dispatch) => {
return dispatch(refreshAccessToken())
.then((didRefresh) => {
console.log('refresh access token returned');
return Promise.resolve();
})
.catch(error => {
console.log('refresh access token failed: ' + error);
return Promise.reject(error);
});
}
}