AWS Amplify React 路由权限控制:实现未登录用户自动重定向

13次阅读

AWS Amplify React 路由权限控制:实现未登录用户自动重定向

本文介绍如何在 aws amplify + react router v6 项目中,为特定路由(如 `/dashboard`)添加认证保护,确保仅已登录用户可访问,未认证用户自动跳转至登录页或提示页。

在基于 AWS Amplify 构建的 react 应用中,实现页面级访问控制是常见需求。单纯使用 withAuthenticator 包裹组件会导致重复渲染登录框、路由循环等问题;而直接在函数组件内异步调用 Auth.currentAuthenticatedUser() 又会因 React 渲染机制(无法在渲染函数中 await)导致白屏或逻辑失效。正确方案是采用路由守卫(Route Guard)模式——通过自定义高阶组件拦截路由访问,在导航前完成身份校验。

以下是推荐的生产就绪实现方式:

✅ 正确做法:创建 RequireAuth 路由守卫组件

// src/components/RequireAuth.jsx import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Auth } from 'aws-amplify';  export function RequireAuth({ children }) {   const navigate = useNavigate();   const [isAuth, setIsAuth] = useState(null); // null 表示校验中,避免闪屏    useEffect(() => {     const checkAuth = async () => {       try {         await Auth.currentAuthenticatedUser(); // 若已登录,返回 CognitoUser 对象         setIsAuth(true);       } catch (error) {         console.warn('User not authenticated:', error);         navigate('/login', {            replace: true,           state: { from: window.location.pathname } // 记录来源页,登录后可跳回         });       }     };      checkAuth();   }, [navigate]);    // 渲染占位符(如加载 Spinner),提升用户体验   if (isAuth === NULL) {     return 
Checking authentication...
; } return isAuth ? children : null; }

✅ 在 app.js 中集成守卫路由

// src/App.js import React from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import { Amplify } from 'aws-amplify'; import awsExports from './aws-exports'; Amplify.configure(awsExports);  import Home from './pages/Home'; import Login from './pages/Login'; import Dashboard from './pages/Dashboard'; import ErrorPage from './pages/ErrorPage';  function App() {   return (                     } />         } />          {/* 受保护路由:仅认证用户可进入 */}                                                }         />          } />               ); }  export default App;

⚠️ 关键注意事项

  • 不要在 element 中直接传入异步函数或条件渲染逻辑:React Router v6 的 element 属性期望一个同步 JSX 元素,而非返回 JSX 的函数。
  • 避免 useEffect 空依赖数组中的裸 Auth.currentAuthenticatedUser():应包裹在 async 函数中并显式 await,否则 .then().catch() 链易丢失错误上下文。
  • 添加加载态反馈:isAuth === null 时显示轻量加载提示,防止白屏,提升 ux
  • 保留来源路径:跳转登录页时通过 state.from 记录原始目标路径,登录成功后可重定向回 /dashboard(需在 Login 组件中读取 useLocation().state?.from)。
  • 服务端校验不可替代前端守卫仅用于体验优化,所有敏感 API 调用仍须在 Amplify 后端(如 graphql Resolver 或 REST Lambda)中进行严格权限验证

✅ 进阶建议:统一认证状态管理

对于中大型应用,推荐结合 Context 或 Zustand 管理全局认证状态,避免每个受保护路由重复调用 Auth.currentAuthenticatedUser()。例如:

// src/contexts/AuthContext.jsx import { createContext, useContext, useEffect, useState } from 'react'; import { Auth } from 'aws-amplify';  const AuthContext = createContext();  export function AuthProvider({ children }) {   const [user, setUser] = useState(null);   const [loading, setLoading] = useState(true);    useEffect(() => {     const checkUser = async () => {       try {         const currentUser = await Auth.currentAuthenticatedUser();         setUser(currentUser);       } catch (e) {         setUser(null);       } finally {         setLoading(false);       }     };     checkUser();   }, []);    return (            {!loading && children}        ); }  export function useAuth() {   const context = useContext(AuthContext);   if (!context) throw new Error('useAuth must be used within AuthProvider');   return context; }

然后在 RequireAuth 中消费该 Context,实现状态复用与响应式更新。

通过以上方案,你将获得健壮、可维护且符合 React 最佳实践的认证路由控制能力,无缝集成 AWS Amplify 身份服务。

text=ZqhQzanResources