Weiß jemand, wie man den Zugriff auf bestimmte Routen im React-Router einschränkt? Ich möchte überprüfen, ob der Benutzer angemeldet ist, bevor ich den Zugriff auf eine bestimmte Route zulasse. Ich dachte, es wäre einfach, aber die Dokumente sind nicht klar, wie es geht.
Ist dies etwas, das ich einrichten sollte, wo ich meine <Route>
Komponenten definiere , oder sollte ich es in meinen Komponentenhandlern behandeln?
<Route handler={App} path="/">
<NotFoundRoute handler={NotFound} name="not-found"/>
<DefaultRoute handler={Login} name="login"/>
<Route handler={Todos} name="todos"/> {/* I want this to be restricted */}
</Route>
javascript
reactjs
react-router
Tanner Semerad
quelle
quelle
Antworten:
Update (16. August 2019)
In React-Router v4 und mit React Hooks sieht dies etwas anders aus. Beginnen wir mit Ihrem
App.js
.export default function App() { const [isAuthenticated, userHasAuthenticated] = useState(false); useEffect(() => { onLoad(); }, []); async function onLoad() { try { await Auth.currentSession(); userHasAuthenticated(true); } catch (e) { alert(e); } } return ( <div className="App container"> <h1>Welcome to my app</h1> <Switch> <UnauthenticatedRoute path="/login" component={Login} appProps={{ isAuthenticated }} /> <AuthenticatedRoute path="/todos" component={Todos} appProps={{ isAuthenticated }} /> <Route component={NotFound} /> </Switch> </div> ); }
Wir verwenden eine
Auth
Bibliothek, um zu überprüfen, ob der Benutzer derzeit authentifiziert ist. Ersetzen Sie dies durch Ihre Auth-Check-Funktion. Wenn ja, setzen wir dasisAuthenticated
Flag auftrue
. Wir tun dies, wenn unsere App zum ersten Mal geladen wird. Erwähnenswert ist auch, dass Sie Ihrer App möglicherweise ein Ladeschild hinzufügen möchten, während die Authentifizierungsprüfung ausgeführt wird, damit Sie die Anmeldeseite nicht jedes Mal flashen, wenn Sie die Seite aktualisieren.Dann geben wir die Flagge an unsere Routen weiter. Wir erstellen zwei Arten von Routen
AuthenticatedRoute
undUnauthenticatedRoute
.Das
AuthenticatedRoute.js
sieht so aus.export default function AuthenticatedRoute({ component: C, appProps, ...rest }) { return ( <Route {...rest} render={props => appProps.isAuthenticated ? <C {...props} {...appProps} /> : <Redirect to={`/login?redirect=${props.location.pathname}${props.location.search}`} />} /> ); }
Es wird geprüft, ob eingestellt
isAuthenticated
isttrue
. Wenn dies der Fall ist, wird die gewünschte Komponente gerendert. Wenn nicht, wird zur Anmeldeseite weitergeleitet.Das
UnauthenticatedRoute.js
sieht dagegen so aus.export default ({ component: C, appProps, ...rest }) => <Route {...rest} render={props => !appProps.isAuthenticated ? <C {...props} {...appProps} /> : <Redirect to="/" />} />;
In diesem Fall wird die gewünschte Komponente gerendert , wenn auf gesetzt
isAuthenticated
istfalse
. Und wenn es auf true gesetzt ist, werden Sie zur Startseite weitergeleitet.Detaillierte Versionen davon finden Sie in unserem Handbuch - https://serverless-stack.com/chapters/create-a-route-that-redirects.html .
Ältere Version
Die akzeptierte Antwort ist korrekt, aber Mixins werden vom React-Team als schädlich eingestuft ( https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html ).
Wenn jemand auf diese Frage stößt und nach der empfohlenen Methode sucht, würde ich vorschlagen, Komponenten höherer Ordnung anstelle von Mixins zu verwenden.
Hier ist ein Beispiel für ein HOC, das prüft, ob der Benutzer angemeldet ist, bevor Sie fortfahren. Wenn der Benutzer nicht angemeldet ist, werden Sie zur Anmeldeseite weitergeleitet. Diese Komponente verwendet eine Requisite namens
isLoggedIn
, dh ein Flag, das Ihre Anwendung speichern kann, um anzuzeigen, ob der Benutzer angemeldet ist.import React from 'react'; import { withRouter } from 'react-router'; export default function requireAuth(Component) { class AuthenticatedComponent extends React.Component { componentWillMount() { this.checkAuth(); } checkAuth() { if ( ! this.props.isLoggedIn) { const location = this.props.location; const redirect = location.pathname + location.search; this.props.router.push(`/login?redirect=${redirect}`); } } render() { return this.props.isLoggedIn ? <Component { ...this.props } /> : null; } } return withRouter(AuthenticatedComponent); }
Und um dieses HOC zu verwenden, wickeln Sie es einfach um Ihre Routen. In Ihrem Beispiel wäre es:
<Route handler={requireAuth(Todos)} name="todos"/>
Ich beschreibe dieses und einige andere Themen in einem detaillierten Schritt-für-Schritt-Tutorial hier - https://serverless-stack.com/chapters/create-a-hoc-that-checks-auth.html
quelle
this.props.isLoggedIn
durch dastrue
Login ersetzt und dieses umgeht ?<Route handler={}/>
ist in v1.0 veraltet, sollten Sie verwenden<Route component={} />
.componentWillMount
werden bald veraltet sein. Lesen Sie es im Blog-Beitrag auf reactjs.org . Stattdessen würde ich mit der Antwort @jacob gehen.Es gibt (jetzt?) Ein Beispiel dafür in den Dokumenten von React Router 4 für
Redirect
import { Route, Redirect } from 'react-router' <Route exact path="/" render={() => ( loggedIn ? ( <Redirect to="/dashboard"/> ) : ( <PublicHomePage/> ) )}/>
quelle
react-router
Wenn Sie einen deklarativen Ansatz für Ihren Router empfehlen, sollten Sie Ihren Router so dumm wie möglich gestalten und vermeiden, dass Ihre Routing-Logik in Ihre Komponenten integriert wird.So können Sie es machen (vorausgesetzt, Sie geben ihm die
loggedIn
Requisite):const DumbRouter = ({ loggedIn }) => ( <Router history={history}> <Switch> {[ !loggedIn && LoggedOutRoutes, loggedIn && LoggedInRouter, <Route component={404Route} /> ]} </Switch> </Router> ); const LoggedInRoutes = [ <Route path="/" component={Profile} /> ]; const LoggedOutRoutes = [ <Route path="/" component={Login} /> ];
quelle
Wenn Sie die Authentifizierung für Ihre gesamte Anwendung verwenden möchten, müssen Sie einige Daten anwendungsweit speichern (z. B. Token). Sie können zwei React-Mixins einrichten, die für die Verwaltung des
$auth
Objekts verantwortlich sind. Dieses Objekt sollte außerhalb dieser beiden Mixins nicht verfügbar sein. Hier ist ein Beispiel dafür:define('userManagement', function() { 'use strict'; var $auth = { isLoggedIn: function () { // return something, e.g. using server-stored data } }; return { Authenticator: { login: function(username, password) { // modify $auth object, or call server, or both } }, NeedsAuthenticatedUser: { statics: { willTransitionTo: function (transition) { if (!$auth.isLoggedIn()) { transition.abort(); } } } } }; });
Dann können Sie einfach das
Authenticator
Mischen mit Ihren Anmeldekomponenten (Anmeldebildschirm, Anmelde-Popup usw.) mischen und diethis.login
Funktion aufrufen , wenn Sie über alle erforderlichen Daten verfügen.Das Wichtigste ist, Ihre Komponenten durch Einmischen zu schützen
NeedsAuthenticatedUser
. Jede Komponente, die einen authentifizierten Benutzer benötigt, muss folgendermaßen aussehen:var um = require('userManagement'); var ProtectedComponent = React.createClass({ mixins: [um.NeedsAuthenticatedUser] // ... }
Beachten Sie, dass
NeedsAuthenticatedUser
die React-Router-API (willTransitionTo
undtransition.abort()
) verwendet wird.quelle
Sie können HOC verwenden und auth ist eine Variable, mit der Sie den Wert true oder false ändern können (Berechtigung).
<Route path="/login" component={SignIn} /> <Route path="/posts" render = {() => (auth ? (<Post />) : (<Redirect to="/login" />))}/>
quelle
private-route.tsx
import {Redirect, Route, RouteProps} from 'react-router'; import * as React from 'react'; interface PrivateRouteProps extends RouteProps { /** * '/login' for example. */ redirectTo: string; /** * If true, won't redirect. * We are using a function instead of a bool, a bool does not seem to be updated * after having successfully authenticated. */ isLogged: () => boolean; } export function PrivateRoute(props: PrivateRouteProps) { // `component: Component` is not typing, it assign the value to a new variable. let { isLogged, redirectTo, component: Component, ...rest }: any = props; // error: JSX type element Component does not have call signature or ... AVOIDED BY ADDING ANY, still work, // and did not find a proper way to fix it. return <Route {...rest} render={(props) => ( isLogged() ? <Component {...props}/> : <Redirect to={{ pathname: redirectTo, state: { from: props.location } }} /> )} />; }
Verwendung:
<PrivateRoute exact={true} path="/admin/" redirectTo={'/admin/login'} isLogged={this.loginService.isLogged} component={AdminDashboardPage}/> <Route path="/admin/login/" component={AdminLoginPage}/>
Basierend auf https://tylermcginnis.com/react-router-protected-routes-authentication/ .
quelle
Normalerweise erhält ein angemeldeter Benutzer ein Token und verwendet dieses Token für die Kommunikation mit dem Server. Normalerweise definieren wir eine Stammseite, und die Dinge bauen auf dieser Seite auf. Diese Stammseite übernimmt die Lokalisierung, Authentifizierung und andere Konfigurationen für Sie.
Hier ist ein Beispiel
Routes = ( <Route path="/" handler={Root}> <Route name="login" handler={Login} /> <Route name="forget" handler={ForgetPassword} /> <Route handler={Main} > <Route name="overview" handler={Overview} /> <Route name="profile" handler={Profile} /> <DefaultRoute handler={Overview} /> </Route> <DefaultRoute handler={Login} /> <NotFoundRoute handler={NotFound} /> </Route> );
Überprüfen Sie auf Ihrer Stammseite, ob das Token null ist, oder authentifizieren Sie das Token beim Server, um festzustellen, ob der Benutzer eine gültige Anmeldung hat.
hoffe das hilft :)
quelle