You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中如何通过刷新令牌恢复会话?AWS Cognito登录后应用重载getCurrentUser()返回null问题求助

React Native中如何通过刷新令牌恢复会话?AWS Cognito登录后应用重载getCurrentUser()返回null问题求助

兄弟我太懂你这种抓狂的感觉了!之前在做React Native + Expo + Cognito的项目时,我也踩过一模一样的坑——登录后一切正常,一重启应用getCurrentUser()就返回null,折腾了好久才搞明白问题所在。

其实核心原因很简单:AWS Cognito的SDK内部缓存是内存级的,应用重启后就清空了,而你用expo-secure-store存的令牌是存在本地持久化存储里的,SDK根本不知道这些令牌的存在,自然拿不到用户信息。解决的关键就是在应用启动时,手动用保存的refreshToken去恢复会话,把令牌同步回SDK的缓存里。

下面是我亲测有效的解决步骤:

1. 应用启动时先读取本地存储的令牌信息

在你的InitialLayout或者路由入口(比如Expo Router的_layout.js)里,先通过expo-secure-store读取之前登录时保存的username和refreshToken:

import * as SecureStore from 'expo-secure-store';

// 在useEffect里执行启动逻辑
useEffect(() => {
  const restoreSession = async () => {
    const username = await SecureStore.getItemAsync('cognito_username');
    const refreshToken = await SecureStore.getItemAsync('cognito_refresh_token');
    
    if (!username || !refreshToken) {
      // 没有保存的令牌,直接跳登录页
      navigation.replace('/login');
      return;
    }
    
    // 有令牌的话,执行会话恢复逻辑
    await refreshCognitoSession(username, refreshToken);
  };

  restoreSession();
}, []);

2. 用refreshToken恢复Cognito会话

接下来实现refreshCognitoSession函数,通过Cognito SDK的refreshSession方法重新获取有效会话,并更新本地存储的令牌,同时把会话同步到SDK缓存中:

import { CognitoUser } from 'amazon-cognito-identity-js';
import { userPool } from '../path-to-your-cognito-config'; // 你的UserPool实例

const refreshCognitoSession = async (username, refreshToken) => {
  return new Promise((resolve, reject) => {
    // 创建CognitoUser实例
    const cognitoUser = new CognitoUser({
      Username: username,
      Pool: userPool,
    });

    // 用refreshToken刷新会话
    cognitoUser.refreshSession(refreshToken, (err, session) => {
      if (err) {
        console.error('会话恢复失败:', err);
        // 比如refreshToken过期了,直接跳登录页
        navigation.replace('/login');
        reject(err);
        return;
      }

      // 刷新成功,更新本地存储的所有令牌
      SecureStore.setItemAsync('cognito_access_token', session.getAccessToken().getJwtToken());
      SecureStore.setItemAsync('cognito_id_token', session.getIdToken().getJwtToken());
      SecureStore.setItemAsync('cognito_refresh_token', session.getRefreshToken().getToken());

      // 这时候再调用getCurrentUser()就能拿到用户了!
      const currentUser = userPool.getCurrentUser();
      // 可以额外验证会话有效性
      currentUser.getSession((sessionErr, validSession) => {
        if (!sessionErr && validSession) {
          console.log('会话恢复成功!');
          resolve(validSession);
        }
      });
    });
  });
};

3. 注意几个避坑点

  • 确保你的userPool实例是全局唯一的,登录和恢复会话时要用同一个实例,不然SDK缓存不会共享
  • 登录成功后,除了存三个令牌,一定要把username也存在本地,因为创建CognitoUser实例必须用到它
  • 处理好刷新失败的情况:比如refreshToken过期、网络错误,这时候要引导用户重新登录
  • 如果你用的是aws-amplify库(比原生SDK更友好),逻辑类似,你可以用Amplify.Auth.refreshSession方法,核心思路还是手动触发会话恢复

这样处理后,下次应用重载时,就会自动用保存的refreshToken恢复会话,getCurrentUser()就能正常返回用户对象了!

备注:内容来源于stack exchange,提问作者Al Nayeem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 17:12:58