Ich versuche, eine Webanwendung mit AWS Amplify zu erstellen. Ich habe die Authentifizierung konfiguriert, möchte aber, dass bestimmte Seiten nur für authentifizierte Benutzer verfügbar sind. Beispielsweise kann die Startseite von jedem gesehen werden, „/dashboard“ jedoch nur von angemeldeten Benutzern. Ich verwende derzeit AWS Amplify für mein Backend und ein React-Frontend und verwende React-Router v6 für die Weiterleitung zwischen Seiten.
Derzeit ist mein Routing-Code sehr einfach (ich verwende React zum ersten Mal) und befindet sich in App.js:
import React from 'react'; import { BrowserRouter, Route, Routes, } from 'react-router-dom'; import Login from './pages/Login'; import Home from './pages/Home'; import Dashboard from './pages/Dashboard'; import ErrorPage from './pages/ErrorPage'; const App = () => { return ( <BrowserRouter> <Routes> <Route exact path="/" element={<Home />} /> <Route path="/login" element={<Login />} /> <Route path="/dashboard" element={<Dashboard />} /> <Route path="*" element={<ErrorPage />} /> </Routes> </BrowserRouter> ); } export default App;
Ich habe zuerst versucht, die Seite, die ich authentifizieren wollte, mit withAuthenticator
zu umbrechen, aber das führte nur zu einer Schleife, die das Anmeldefeld anzeigte.
function Dashboard({ signOut, user }) { return ( <> <h1>Hello {user.username}, this is still in development.</h1> <button onClick={signOut}> Sign out</button> </> ); } export default withAuthenticator(Dashboard);
Ich habe auch versucht, eine Funktion hinzuzufügen, um zu prüfen, ob der Benutzer authentifiziert ist, und etwas anderes zurückzugeben, aber diese zeigt nur einen leeren Bildschirm für authentifizierte und nicht authentifizierte Benutzer. Ich denke, das liegt daran, dass es async
ist, aber ich kenne mich mit React nicht gut genug aus, um zu verstehen, warum und wie man das Problem beheben kann.
async function isAuthed() { try { await Auth.currentAuthenticatedUser(); return true; } catch(e) { return false; } } async function Dashboard() { if (await isAuthed()) { return ( <> <h1>Hello, this is still in development.</h1> </> ); } else { return ( <> <h1>Please login to view this page.</h1> </> ) } }
Ich habe auch versucht herauszufinden, ob es eine Möglichkeit gibt, asynchron weiterzuleiten, bin mir aber nicht sicher, wie ich das implementieren soll.
Herausgeber:
Die Lösung von@Jlove funktioniert bereits wie erwartet, mein aktualisierter App.js
Routing-Code lautet wie folgt:
import React, { useState, useEffect } from 'react'; import { BrowserRouter, Route, Routes, useNavigate, } from 'react-router-dom'; import { Amplify, Auth } from 'aws-amplify' import Login from './pages/Login'; import Home from './pages/Home'; import Dashboard from './pages/Dashboard'; import ErrorPage from './pages/ErrorPage'; import Unauthenticated from './pages/Unauthenticated'; function RequireAuth({ children }) { const navigate = useNavigate(); const [isAuth, setIsAuth] = useState(null); useEffect(() => { Auth.currentAuthenticatedUser() .then(() => setIsAuth(true)) .catch(() => { navigate("/unauthenticated") }) }, []) return isAuth && children; } const App = () => { return ( <BrowserRouter> <Routes> <Route exact path="/" element={<Home />} /> <Route path="/login" element={<Login />} /> <Route path="/dashboard" element={ <RequireAuth> <Dashboard /> </RequireAuth> } /> <Route path="*" element={<ErrorPage />} /> <Route path="/unauthenticated" element={<Unauthenticated />} /> </Routes> </BrowserRouter> ); } export default App;
您将希望将保护路由的逻辑与每个路由渲染的内容分开。不要将身份验证与您要在路由上呈现的UI/内容组件混合在一起。
一种常见的保护模式是使用布局路由来包装您想要保护访问权限的整个路由组。您将创建一个布局路由组件,触发一个效果来检查当前用户的身份验证状态,并有条件地返回:
Outlet
(如果用户已经通过身份验证)这样可以防止(a)在知道用户未经身份验证之前意外访问受保护的页面,以及(b)在知道用户已经通过身份验证之前意外重定向到登录页面。
示例:
包装需要受保护的路由。
以下是一种方法,通过将组件路由包装在授权组件中来实现:
这里的目标是基于
Auth
返回的结果来保护您的路由。如果Auth
选择了catch路由,利用路由器将用户导航到未经授权的页面。