2015-06-27 9 views
32

Qualcuno sa come limitare l'accesso a percorsi particolari in react-router? Voglio verificare se l'utente è loggato prima di consentire l'accesso a una particolare rotta. Ho pensato che sarebbe semplice, ma i documenti non sono chiari come farlo.Come limitare l'accesso ai percorsi nel react-router?

È qualcosa che dovrei impostare in cui definisco i miei componenti <Route> o dovrei gestirlo all'interno dei miei gestori di componenti?

<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

Se non sono connessi, reindirizzare al gestore di accesso. Si noti inoltre che il client ha accesso a tutto il JS che carica, quindi non memorizzare informazioni sensibili in esso. –

+0

@Tanner Semerad avete qualche repository github su come l'avete raggiunto brevemente. – jit

+0

@jit Io no, mi dispiace. La risposta di miciek di seguito era ciò di cui avevo bisogno, ma tieni presente che questo era prima del react-router 1.0. So che un certo numero di cose sono cambiate da quando è stato rilasciato 1.0, ma è per lo più simile. –

risposta

32

La risposta accettata è corretta ma i Mixin sono considerati dannosi (https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html) dal team di React.

Se qualcuno trova questa domanda e sta cercando il modo consigliato per farlo, suggerirei di utilizzare Componenti ordine superiore invece di Mixin.

Ecco un esempio di un HOC che verificherà se l'utente è connesso prima di procedere. E se l'utente non ha effettuato l'accesso, ti reindirizzerà alla pagina di accesso. Questo componente prende un oggetto di scena chiamato isLoggedIn, che è fondamentalmente una bandiera che l'applicazione può memorizzare per indicare se l'utente è connesso.

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

e di utilizzare questo HOC, basta avvolgerlo intorno ai vostri percorsi.Nel caso del vostro esempio, sarebbe:

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

copro questo e pochi altri argomenti in una dettagliata guida passo-passo qui - http://serverless-stack.com/chapters/create-a-hoc-that-checks-auth.html

+0

Se il mio codice originale stava usando , come faccio a farlo funzionare con questo esempio? – Bran

+0

Ho un codice molto simile, ma la mia domanda è, è abbastanza sicuro? Voglio dire che un utente malintenzionato può modificare il codice minorato JS in modo tale che la sostituzione di 'this.props.isLoggedIn' con' true' e l'accesso di bypass? –

+1

@karimelhelawy Questo è vero e per questo è necessario imporre l'autenticazione nell'API del server. – cubrr

-2

in genere un utente connesso riceverà un token e utilizza questo token per qualsiasi comunicazione con il server. Quello che facciamo di solito è definire una pagina radice, e le cose si costruiscono in cima a quella pagina. questa pagina radice esegue la localizzazione, l'autenticazione e altre configurazioni per te.

Ecco un esempio

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

sulla tua pagina principale, verificare la presenza di nulla di token o autenticare il token con il server per vedere se l'utente è valido login.

Spero che questo aiuti :)

+2

Esatto, quindi come dovrei interrompere la classe "Panoramica" da importare se Auth non è stata eseguita, o come appare il gestore "Principale" ? Ad esempio, che cosa succede se "Panoramica" ha una dipendenza che richiede l'esecuzione di un'app autenticata? Poiché viene importato per essere eseguito sul router, anche tutte le sue dipendenze saranno state importate e quindi hai un'app rotta, giusto? –

+0

Questo non risponde alla domanda che è stata posta – Herm

2

Se si desidera utilizzare l'autenticazione attraverso tutta l'applicazione, è necessario memorizzare alcune a livello di applicazione dei dati (ad esempio token). È possibile configurare due mixin React responsabili della gestione dell'oggetto $auth. Questo oggetto non dovrebbe essere disponibile al di fuori di questi due mix. Ecco esempio di che:

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

allora si può solo mixin Authenticator miscelazione per i componenti d'accesso (schermata di login, login pop-up, ecc) e chiamare this.login funzione quando si dispone di tutti i dati necessari.

La cosa più importante è proteggere i componenti mixando nel mix NeedsAuthenticatedUser. Ogni componente che ha bisogno di utente autenticato dovrà guardare così:

var um = require('userManagement'); 

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

Nota che NeedsAuthenticatedUser utilizza API reagire-router (willTransitionTo e transition.abort()).

+0

Grazie, è esattamente ciò di cui avevo bisogno. –

+2

I mixaggi sono una cattiva idea per andare avanti. [Leggi di più] (https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750#.egtnavn6d) – boldnik

+0

Un modo molto migliore che ho trovato: https: // github.com/reactjs/react-router/tree/master/examples/auth-flow – boldnik

0

react-router incoraggia un approccio dichiarativo per il router, dovresti rendere il router più stupido possibile ed evitare di inserire la logica di routing nei tuoi componenti.

Ecco come si può fare (supponendo si passa la loggedIn prop): (? Ora)

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

V'è un esempio di questo in Reagire docs del Router 4 per Redirect

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

<Route exact path="/" render={() => (
    loggedIn ? (
    <Redirect to="/dashboard"/> 
) : (
    <PublicHomePage/> 
) 
)}/> 
Problemi correlati