2017-08-12 125 views
0

我是React Native的新手,我遇到的第一个障碍之一是当我的访问令牌到期时刷新它。基本的实现是有一个访问令牌和一个刷新令牌。访问令牌到期并在授权头中发送刷新令牌以刷新访问令牌。基于this SO帖子,我实现了一个中间件,它在每个API调用期间检查我们的访问令牌是否即将到期。如果是这样,它会启动一个动作创建器,它会使API调用刷新并确认新的访问令牌。我只在这里展示刷新电话,以免过度复杂。使用React Native和Redux进行OAuth令牌刷新

问题是检测刷新需求的中间件也被刷新调用本身命中,这导致无限循环并最终超出调用堆栈大小。我想知道是否有人能够帮助我找到解决办法,或者告诉我我很笨,并提供更好的整体解决方案。任何指导非常感谢。谢谢!

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

例如,您可以通过元数据在需要访问令牌,然后到中间件检查行动,或者您需要验证基于元数据的标记。

行动文件

// 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); 
     }); 
    } 
}