2015-06-27 16 views
32

Czy ktoś wie, jak ograniczyć dostęp do określonych tras w routerze reagowania? Chcę sprawdzić, czy użytkownik jest zalogowany przed zezwoleniem na dostęp do konkretnej trasy. Myślałem, że to będzie proste, ale doktorzy nie wiedzą, jak to zrobić.Jak ograniczyć dostęp do tras w routerze reagowania?

Czy jest to coś, co powinienem skonfigurować, definiując moje komponenty <Route>, czy też powinienem je obsługiwać wewnątrz modułów obsługi komponentów?

<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> 
+0

Jeśli nie są zalogowani, przekieruj do obsługi logowania. Zwróć też uwagę, że klient ma dostęp do wszystkich ładowanych JS, więc nie przechowuj w nim poufnych informacji. –

+0

@ Tanner Semerad masz jakieś repozytorium github o tym, jak to szybko osiągnąłeś. – jit

+0

@jit Nie, przepraszam. Odpowiedź od miciek poniżej była tym, czego potrzebowałem, ale pamiętaj, że to było przed routerem-reakcją 1.0. Wiem, że wiele rzeczy zmieniło się od wydania 1.0, ale jest w większości podobne. –

Odpowiedz

32

Przyjęta odpowiedź jest poprawna, ale Mixiny są uważane za szkodliwe (https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html) przez zespół Reaktorów.

Jeśli ktoś natknie się na to pytanie i szuka zalecanego sposobu, aby to zrobić, sugeruję użycie komponentów wyższego rzędu zamiast Mixins.

Oto przykład HOC, który sprawdzi, czy użytkownik jest zalogowany przed kontynuowaniem. A jeśli użytkownik nie jest zalogowany, przekieruje Cię na stronę logowania. Komponent ten wykonuje rekwizyt nazwie isLoggedIn, który jest w zasadzie flag że aplikacja może przechowywać do określenia, czy użytkownik jest zalogowany.

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); 
} 

I korzystać z tej hoc, tylko owinąć go wokół swoich tras.W przypadku Twojego przykład, byłoby:

<Route handler={requireAuth(Todos)} name="todos"/> 

omówię ten i kilka innych tematów w szczegółowym krok po kroku samouczek tutaj - http://serverless-stack.com/chapters/create-a-hoc-that-checks-auth.html

+0

Jeśli mój oryginalny kod korzystał z , w jaki sposób sprawiłabym, żeby działał z tym przykładem? – Bran

+0

Mam bardzo podobny kod, ale moje pytanie brzmi, czy jest wystarczająco zabezpieczony? Mam na myśli, że atakujący może zmienić miniony kod JS tak, że zastępuje on 'this.props.isLoggedIn' przez' true' i pomija logowanie? –

+1

@karimelhelawy To prawda i dlatego musisz wymusić uwierzytelnianie w swoim interfejsie API serwera. – cubrr

-2

zwykle zalogowany użytkownik otrzyma token i używa tego tokena do komunikacji z serwerem. Zazwyczaj definiujemy stronę główną i rzeczy budowane na górze tej strony. ta strona główna wykonuje dla Ciebie lokalizacje, uwierzytelnianie i inne konfiguracje.

Oto przykład

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> 
); 

na swojej stronie głównego, sprawdź tokena null lub uwierzytelniania token z serwerem w celu sprawdzenia, czy użytkownik jest ważny logowania.

nadzieję, że to pomoże :)

+2

Dobrze, więc jak zatrzymałbym klasę "Przegląd" do zaimportowania, jeśli Auth nie przeszedł, lub jak wygląda "Main" handler ? Na przykład, jeśli "Przegląd" ma zależność wymagającą uruchomienia uwierzytelnionej aplikacji? Ponieważ jest importowany do uruchomienia na routerze, wszystkie jego zależności również zostały zaimportowane, a zatem masz zepsutą aplikację, prawda? –

+0

To nie odpowiada na pytanie, które zostało zadane. – Herm

2

Jeśli chcesz korzystać z uwierzytelniania w poprzek całej aplikacji, trzeba przechowywać niektóre dane aplikacji szeroki (np tokena). Możesz skonfigurować dwa miksy React, które są odpowiedzialne za zarządzanie obiektem $auth. Ten obiekt nie powinien być dostępny poza tymi dwoma miksami. Oto przykład, że:

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(); 
        } 
       } 
      } 
     } 
    }; 
}); 

Następnie można po prostu mixin Authenticator mieszanie się komponentów logowania (ekran logowania, logowanie popup, etc) i nazywają this.login funkcję, gdy masz wszystkie dane niezbędne.

Najważniejszą rzeczą jest ochrona komponentów poprzez mieszanie w mieszaninie NeedsAuthenticatedUser. Każdy element, który musi uwierzytelniony użytkownik będzie musiał wyglądać tak:

var um = require('userManagement'); 

var ProtectedComponent = React.createClass({ 
    mixins: [um.NeedsAuthenticatedUser] 
    // ... 
} 

Zauważ, że NeedsAuthenticatedUser wykorzystuje reagowania-Router API (willTransitionTo i transition.abort()).

+0

Dziękuję, to jest dokładnie to, czego potrzebowałem. –

+2

Mixins to zły pomysł, aby przejść. [Czytaj więcej] (https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750#.egtnavn6d) – boldnik

+0

O wiele lepszy sposób, jaki znalazłem: https: // github.com/reactjs/react-router/tree/master/examples/auth-flow – boldnik

0

react-router zachęca deklaratywny podejście do routera, powinieneś ustawić router tak głupio, jak to możliwe i unikać umieszczania logiki routingu w komponentach.

Oto w jaki sposób można to zrobić (zakładając, że przejdzie mu loggedIn rekwizyt): (? Teraz)

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} /> 
]; 
3

Jest to przykład tego w React docs Ruter 4 za Redirect

import { Route, Redirect } from 'react-router' 

<Route exact path="/" render={() => (
    loggedIn ? (
    <Redirect to="/dashboard"/> 
) : (
    <PublicHomePage/> 
) 
)}/> 
Powiązane problemy