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
相关产品推荐
相关产品推荐

