本文介绍如何在 aws amplify + react router v6 项目中,为特定路由(如 `/dashboard`)添加认证保护,确保仅已登录用户可访问,未认证用户自动跳转至登录页或提示页。
在基于 AWS Amplify 构建的 React 应用中,实现页面级访问控制是常见需求。单纯使用 withAuthenticator 包裹组件会导致重复渲染登录框、路由循环等问题;而直接在函数组件内异步调用 Auth.currentAuthenticatedUser() 又会因 React 渲染机制(无法在渲染函数中 await)导致白屏或逻辑失效。正确方案是采用路由守卫(Route Guard)模式——通过自定义高阶组件拦截路由访问,在导航前完成身份校验。
以下是推荐的生产就绪实现方式:
// 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;
}// 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;
henticatedUser():应包裹在 async 函数中并显式 await,否则 .then().catch() 链易丢失错误上下文。对于中大型应用,推荐结合 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 身份服务。