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

如何在React+Redux应用中实现AWS Amplify的currentSession维持登录状态

如何在结合Redux的React应用中维持AWS Amplify登录状态(页面刷新后)

我之前也遇到过完全一样的问题——页面刷新后Redux store清空,用户登录状态丢失,UI直接回到未登录状态。结合AWS Amplify和Redux的最佳实践其实分两步:恢复Amplify的会话状态并同步到Redux,同时持久化Redux中需要保留的非敏感数据。下面是具体的实现方案:

核心思路

  1. 页面刷新后,Redux store会被重置,所以我们需要在应用启动时主动检查Amplify的当前会话有效性。
  2. 使用Redux持久化工具(比如redux-persist)保存store中需要保留的非敏感数据(比如用户基本信息、应用偏好),避免这些数据随页面刷新丢失。
  3. 监听Amplify的会话变化事件,确保Redux状态始终和Amplify的认证状态保持同步。

具体实现步骤

1. 配置Redux持久化

首先安装redux-persist(和Redux Toolkit适配性很好):

npm install redux-persist

然后修改你的Redux store配置,指定需要持久化的slice,同时处理Amplify对象的序列化问题:

// store.js
import { configureStore, combineReducers } from '@reduxjs/toolkit';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage'; // 默认使用localStorage
import authReducer from './slices/authSlice';
import userPreferencesReducer from './slices/userPreferencesSlice';

// 持久化配置:只保留需要的slice,避免存储敏感数据
const persistConfig = {
  key: 'root',
  storage,
  whitelist: ['auth', 'userPreferences'], // 这里列你想保留的slice
};

// 包装reducer
const rootReducer = combineReducers({
  auth: authReducer,
  userPreferences: userPreferencesReducer,
  // 其他不需要持久化的reducer放在这里
});

const persistedReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: false, // 关闭序列化检查,因为Amplify的会话对象可能包含不可序列化的属性
    }),
});

export const persistor = persistStore(store);

2. 在应用启动时检查并同步会话

在你的根组件(比如App.jsx)中,使用useEffect在组件挂载时检查Amplify的当前会话,并将状态同步到Redux:

// App.jsx
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { Auth } from 'aws-amplify';
import { setUser, setSession } from './store/slices/authSlice';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from './store';
import { BrowserRouter as Router } from 'react-router-dom'; // 如果用路由的话

function App() {
  const dispatch = useDispatch();

  useEffect(() => {
    // 检查当前会话的异步函数
    const checkAuthStatus = async () => {
      try {
        // 获取Amplify的当前会话
        const session = await Auth.currentSession();
        // 获取当前认证用户信息
        const user = await Auth.currentAuthenticatedUser();
        
        // 将会话和用户信息同步到Redux
        dispatch(setSession(session));
        dispatch(setUser(user));
      } catch (error) {
        // 会话无效(比如用户未登录、令牌过期),重置Redux中的认证状态
        dispatch(setSession(null));
        dispatch(setUser(null));
        // 可以在这里跳转到登录页
        // navigate('/login');
      }
    };

    checkAuthStatus();

    // 监听Amplify的会话变化事件,确保状态同步
    const authListener = Auth.listen((data) => {
      switch (data.payload.event) {
        case 'signOut':
          // 用户登出时重置Redux状态
          dispatch(setSession(null));
          dispatch(setUser(null));
          break;
        case 'tokenRefresh':
          // 令牌自动刷新后,更新Redux中的会话
          Auth.currentSession().then(session => {
            dispatch(setSession(session));
          });
          break;
        // 其他事件可以根据需要处理,比如signIn
      }
    });

    // 组件卸载时清理监听
    return () => authListener();
  }, [dispatch]);

  return (
    <PersistGate loading={<div>加载中...</div>} persistor={persistor}>
      <Router>
        {/* 你的应用路由和页面组件 */}
      </Router>
    </PersistGate>
  );
}

export default App;

3. 编写Auth Slice

创建一个Redux slice来管理认证状态:

// slices/authSlice.js
import { createSlice } from '@reduxjs/toolkit';

const initialState = {
  user: null, // 存储用户基本信息
  session: null, // 存储会话对象(注意:不要持久化敏感令牌,Amplify会自己管理)
};

const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    setUser: (state, action) => {
      state.user = action.payload;
    },
    setSession: (state, action) => {
      state.session = action.payload;
    },
  },
});

export const { setUser, setSession } = authSlice.actions;
export default authSlice.reducer;

关键注意事项

  • 不要持久化敏感令牌:Amplify会自动将idToken、accessToken等存储在安全的位置(比如浏览器的localStorage,可通过Amplify配置修改),我们只需要在Redux中存储会话状态和用户基本信息即可,避免手动存储敏感数据带来的安全风险。
  • 处理序列化问题:因为Amplify的CognitoUserSession对象包含一些不可序列化的方法,所以我们关闭了Redux Toolkit的serializableCheck,如果担心这个,可以只存储会话中的必要字段(比如令牌字符串),而不是整个对象。
  • 加载状态处理:PersistGate的loading属性可以设置一个加载组件,避免在持久化数据恢复前显示未授权的UI。

内容的提问来源于stack exchange,提问作者Skate to Eat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:10:34