Come implementare percorsi autenticati in React Router 4?


122

Stavo cercando di implementare percorsi autenticati, ma ho scoperto che React Router 4 ora impedisce che funzioni:

<Route exact path="/" component={Index} />
<Route path="/auth" component={UnauthenticatedWrapper}>
    <Route path="/auth/login" component={LoginBotBot} />
</Route>
<Route path="/domains" component={AuthenticatedWrapper}>
    <Route exact path="/domains" component={DomainsIndex} />
</Route>

L'errore è:

Attenzione: non dovresti usare <Route component>e <Route children>nello stesso percorso; <Route children>verrà ignorato

In tal caso, qual è il modo corretto per implementarlo?

Appare in react-router(v4) documenti, suggerisce qualcosa di simile

<Router>
    <div>
    <AuthButton/>
    <ul>
        <li><Link to="/public">Public Page</Link></li>
        <li><Link to="/protected">Protected Page</Link></li>
    </ul>
    <Route path="/public" component={Public}/>
    <Route path="/login" component={Login}/>
    <PrivateRoute path="/protected" component={Protected}/>
    </div>
</Router>

Ma è possibile ottenere questo risultato raggruppando insieme un mucchio di vie?


AGGIORNARE

Ok, dopo alcune ricerche, mi è venuto in mente questo:

import React, {PropTypes} from "react"
import {Route} from "react-router-dom"

export default class AuthenticatedRoute extends React.Component {
  render() {
    if (!this.props.isLoggedIn) {
      this.props.redirectToLogin()
      return null
    }
    return <Route {...this.props} />
  }
}

AuthenticatedRoute.propTypes = {
  isLoggedIn: PropTypes.bool.isRequired,
  component: PropTypes.element,
  redirectToLogin: PropTypes.func.isRequired
}

È corretto inviare un'azione in render()esso sembra sbagliato. Non sembra proprio corretto con componentDidMounto con qualche altro hook?


meglio fare su componetWillMount se non si utilizza il rendering lato server.
mfahadi

@mfahadi, grazie per l'input. Non sto ancora usando SSR, ma se voglio usarlo in futuro, lo tengo nel rendering? Inoltre, se l'utente viene reindirizzato componentWillMount, potrà mai vedere l'output renderizzato anche per una frazione di secondo?
Jiew Meng

Mi dispiace davvero dire che componentWillMount()non è chiamato su SSR, è componentDidMount()che non è chiamato. come componentWillMount()è stato chiamato prima render(), quindi l'utente non vedrà nulla del nuovo componente. quindi è il posto migliore per controllare.
mfahadi

1
potresti semplicemente usare il <Redirect to="/auth"> dai documenti invece di chiamare l'azione di spedizione
Fuzail l'Corder

Risposte:


239

Dovrai utilizzare il Redirectcomponente. Esistono diversi approcci a questo problema. Eccone uno che mi piace, ho un componente PrivateRoute che accetta un authedprop e quindi esegue il rendering in base a tali oggetti.

function PrivateRoute ({component: Component, authed, ...rest}) {
  return (
    <Route
      {...rest}
      render={(props) => authed === true
        ? <Component {...props} />
        : <Redirect to={{pathname: '/login', state: {from: props.location}}} />}
    />
  )
}

Ora i tuoi Routepossono assomigliare a questo

<Route path='/' exact component={Home} />
<Route path='/login' component={Login} />
<Route path='/register' component={Register} />
<PrivateRoute authed={this.state.authed} path='/dashboard' component={Dashboard} />

Se sei ancora confuso, ho scritto questo post che potrebbe aiutarti: percorsi protetti e autenticazione con React Router v4


2
Oh questo è simile alla mia soluzione, ma usa <Redirect />. Il problema è <Redirect />che non sembra funzionare con redux nel mio caso? Devo inviare un'azione
Jiew Meng

3
Non so perché, ma l'aggiunta ha state: {from: props.location}}}causato un maximum call stack exceeded. Ho dovuto rimuoverlo. Puoi spiegare perché questa opzione è utile @Tyler McGinnis?
martpie

@KeitIG ​​È strano. È utile perché ti dice da dove vieni. Un esempio potrebbe essere se si desidera che l'utente si autentichi, quindi, una volta autenticato, riportalo alla pagina a cui stava tentando di accedere prima di reindirizzarlo.
Tyler McGinnis

6
@faraz Questo spiega la ({component: Component, ...rest})sintassi. Ho avuto la stessa domanda lol! stackoverflow.com/a/43484565/6502003
protoEvangelion

2
@TylerMcGinnis E se avessimo bisogno di usare la funzione render per passare gli oggetti di scena al componente?
C Bauer

16

Tnx Tyler McGinnis per la soluzione. Faccio la mia idea dall'idea di Tyler McGinnis.

const DecisionRoute = ({ trueComponent, falseComponent, decisionFunc, ...rest }) => {
  return (
    <Route
      {...rest}

      render={
        decisionFunc()
          ? trueComponent
          : falseComponent
      }
    />
  )
}

Puoi implementarlo in questo modo

<DecisionRoute path="/signin" exact={true}
            trueComponent={redirectStart}
            falseComponent={SignInPage}
            decisionFunc={isAuth}
          />

decisionFunc solo una funzione che restituisce true o false

const redirectStart = props => <Redirect to="/orders" />

8

(Utilizzo di Redux per la gestione dello stato)

Se l'utente tenta di accedere a qualsiasi URL, per prima cosa controllerò se il token di accesso è disponibile, se non reindirizzerò alla pagina di accesso. Una volta che l'utente accede utilizzando la pagina di accesso, lo memorizziamo in localstorage e nel nostro stato di redux. (localstorage o cookies .. per ora teniamo questo argomento fuori contesto).
dal momento che lo stato di redux come aggiornato e privateroutes verranno riesaminati. ora abbiamo il token di accesso, quindi reindirizzeremo alla home page.

Memorizza anche i dati del payload dell'autorizzazione decodificata nello stato redux e passali al contesto di reazione. (Non dobbiamo usare il contesto ma per accedere all'autorizzazione in nessuno dei nostri componenti figlio nidificati rende facile l'accesso dal contesto invece di collegare ogni singolo componente figlio a redux) ..

È possibile accedere a tutte le rotte che non necessitano di ruoli speciali direttamente dopo il login .. Se ha bisogno di un ruolo come admin (abbiamo creato una rotta protetta che controlla se aveva il ruolo desiderato se non reindirizza a componenti non autorizzati)

allo stesso modo in qualsiasi componente se devi disabilitare il pulsante o qualcosa in base al ruolo.

semplicemente puoi farlo in questo modo

const authorization = useContext(AuthContext);
const [hasAdminRole] = checkAuth({authorization, roleType:"admin"});
const [hasLeadRole] = checkAuth({authorization, roleType:"lead"});
<Button disable={!hasAdminRole} />Admin can access</Button>
<Button disable={!hasLeadRole || !hasAdminRole} />admin or lead can access</Button>

Che cosa succede se l'utente tenta di inserire un token fittizio in localstorage. Poiché abbiamo il token di accesso, reindirizzeremo al componente home. Il mio componente home effettuerà una chiamata rest per acquisire i dati, poiché il token jwt era fittizio, la chiamata rest restituirà un utente non autorizzato. Quindi chiamo logout (che cancellerà localstorage e reindirizzerà nuovamente alla pagina di accesso). Se la home page ha dati statici e non effettua alcuna chiamata API (allora dovresti avere una chiamata API per la verifica del token nel backend in modo da poter controllare se il token è REALE prima di caricare la home page)

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, Switch } from 'react-router-dom';
import history from './utils/history';


import Store from './statemanagement/store/configureStore';
import Privateroutes from './Privateroutes';
import Logout from './components/auth/Logout';

ReactDOM.render(
  <Store>
    <Router history={history}>
      <Switch>
        <Route path="/logout" exact component={Logout} />
        <Route path="/" exact component={Privateroutes} />
        <Route path="/:someParam" component={Privateroutes} />
      </Switch>
    </Router>
  </Store>,
  document.querySelector('#root')
);

History.js

import { createBrowserHistory as history } from 'history';

export default history({});

Privateroutes.js

import React, { Fragment, useContext } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { AuthContext, checkAuth } from './checkAuth';
import App from './components/App';
import Home from './components/home';
import Admin from './components/admin';
import Login from './components/auth/Login';
import Unauthorized from './components/Unauthorized ';
import Notfound from './components/404';

const ProtectedRoute = ({ component: Component, roleType, ...rest })=> { 
const authorization = useContext(AuthContext);
const [hasRequiredRole] = checkAuth({authorization, roleType});
return (
<Route
  {...rest}
  render={props => hasRequiredRole ? 
  <Component {...props} /> :
   <Unauthorized {...props} />  } 
/>)}; 

const Privateroutes = props => {
  const { accessToken, authorization } = props.authData;
  if (accessToken) {
    return (
      <Fragment>
       <AuthContext.Provider value={authorization}>
        <App>
          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/login" render={() => <Redirect to="/" />} />
            <Route exact path="/home" component={Home} />
            <ProtectedRoute
            exact
            path="/admin"
            component={Admin}
            roleType="admin"
          />
            <Route path="/404" component={Notfound} />
            <Route path="*" render={() => <Redirect to="/404" />} />
          </Switch>
        </App>
        </AuthContext.Provider>
      </Fragment>
    );
  } else {
    return (
      <Fragment>
        <Route exact path="/login" component={Login} />
        <Route exact path="*" render={() => <Redirect to="/login" />} />
      </Fragment>
    );
  }
};

// my user reducer sample
// const accessToken = localStorage.getItem('token')
//   ? JSON.parse(localStorage.getItem('token')).accessToken
//   : false;

// const initialState = {
//   accessToken: accessToken ? accessToken : null,
//   authorization: accessToken
//     ? jwtDecode(JSON.parse(localStorage.getItem('token')).accessToken)
//         .authorization
//     : null
// };

// export default function(state = initialState, action) {
// switch (action.type) {
// case actionTypes.FETCH_LOGIN_SUCCESS:
//   let token = {
//                  accessToken: action.payload.token
//               };
//   localStorage.setItem('token', JSON.stringify(token))
//   return {
//     ...state,
//     accessToken: action.payload.token,
//     authorization: jwtDecode(action.payload.token).authorization
//   };
//    default:
//         return state;
//    }
//    }

const mapStateToProps = state => {
  const { authData } = state.user;
  return {
    authData: authData
  };
};

export default connect(mapStateToProps)(Privateroutes);

checkAuth.js

import React from 'react';

export const AuthContext = React.createContext();

export const checkAuth = ({ authorization, roleType }) => {
  let hasRequiredRole = false;

  if (authorization.roles ) {
    let roles = authorization.roles.map(item =>
      item.toLowerCase()
    );

    hasRequiredRole = roles.includes(roleType);
  }

  return [hasRequiredRole];
};

CAMPIONE DI GETTONI JWT DECODIFICATO

{
  "authorization": {
    "roles": [
      "admin",
      "operator"
    ]
  },
  "exp": 1591733170,
  "user_id": 1,
  "orig_iat": 1591646770,
  "email": "hemanthvrm@stackoverflow",
  "username": "hemanthvrm"
}

E come gestisci l'accesso diretto a Signin? Se un utente sa di non aver effettuato l'accesso, dovrebbe avere un'opzione per accedere direttamente all'accesso, giusto?
carkod

@carkod ... Per impostazione predefinita, se tenta di accedere a qualsiasi percorso, verrà reindirizzato alla pagina di accesso ... (poiché non avrà il token)
Hemanthvrm

@carkod .. una volta che l'utente ha cliccato su logout oppure il mio token di aggiornamento jwt scade .. chiamo la funzione logout dove pulisco localstorage e aggiorna la finestra ... quindi localstorage non avrà token..si reindirizzerà automaticamente alla pagina di accesso
Hemanthvrm

ne ho una versione migliore per coloro che usano redux..aggiornerò la mia risposta in un paio di giorni..grazie -
Hemanthvrm

3

installa React-Router-Dom

quindi creare due componenti uno per gli utenti validi e l'altro per gli utenti non validi.

provalo su app.js

import React from 'react';

import {
BrowserRouter as Router,
Route,
Link,
Switch,
Redirect
} from 'react-router-dom';

import ValidUser from "./pages/validUser/validUser";
import InValidUser from "./pages/invalidUser/invalidUser";
const loggedin = false;

class App extends React.Component {
 render() {
    return ( 
      <Router>
      <div>
        <Route exact path="/" render={() =>(
          loggedin ? ( <Route  component={ValidUser} />)
          : (<Route component={InValidUser} />)
        )} />

        </div>
      </Router>
    )
  }
}
export default App;

4
Per percorso? Questo non scalerà.
Jim G.

3

Basato sulla risposta di @Tyler McGinnis . Ho adottato un approccio diverso utilizzando la sintassi ES6 e percorsi nidificati con componenti avvolti:

import React, { cloneElement, Children } from 'react'
import { Route, Redirect } from 'react-router-dom'

const PrivateRoute = ({ children, authed, ...rest }) =>
  <Route
    {...rest}
    render={(props) => authed ?
      <div>
        {Children.map(children, child => cloneElement(child, { ...child.props }))}
      </div>
      :
      <Redirect to={{ pathname: '/', state: { from: props.location } }} />}
  />

export default PrivateRoute

E usandolo:

<BrowserRouter>
  <div>
    <PrivateRoute path='/home' authed={auth}>
      <Navigation>
        <Route component={Home} path="/home" />
      </Navigation>
    </PrivateRoute>

    <Route exact path='/' component={PublicHomePage} />
  </div>
</BrowserRouter>

2

So che è passato un po 'di tempo, ma ho lavorato a un pacchetto npm per rotte private e pubbliche.

Ecco come creare un percorso privato:

<PrivateRoute exact path="/private" authed={true} redirectTo="/login" component={Title} text="This is a private route"/>

E puoi anche creare percorsi pubblici a cui solo l'utente non autorizzato può accedere

<PublicRoute exact path="/public" authed={false} redirectTo="/admin" component={Title} text="This route is for unauthed users"/>

Spero possa essere d'aiuto!


puoi fornire altri esempi, comprese tutte le importazioni e i wrapping, ad esempio in 2 publicroutes, 2 route private e 2 PropsRoute, nell'App.js principale? grazie
MH

2

Ho implementato utilizzando-

<Route path='/dashboard' render={() => (
    this.state.user.isLoggedIn ? 
    (<Dashboard authenticate={this.authenticate} user={this.state.user} />) : 
    (<Redirect to="/login" />)
)} />

gli oggetti di autenticazione verranno passati ai componenti, ad esempio la registrazione, utilizzando lo stato utente che può essere modificato. AppRoutes completi-

import React from 'react';
import { Switch, Route } from 'react-router-dom';
import { Redirect } from 'react-router';

import Home from '../pages/home';
import Login from '../pages/login';
import Signup from '../pages/signup';
import Dashboard from '../pages/dashboard';

import { config } from '../utils/Config';

export default class AppRoutes extends React.Component {

    constructor(props) {
        super(props);

        // initially assuming that user is logged out
        let user = {
            isLoggedIn: false
        }

        // if user is logged in, his details can be found from local storage
        try {
            let userJsonString = localStorage.getItem(config.localStorageKey);
            if (userJsonString) {
                user = JSON.parse(userJsonString);
            }
        } catch (exception) {
        }

        // updating the state
        this.state = {
            user: user
        };

        this.authenticate = this.authenticate.bind(this);
    }

    // this function is called on login/logout
    authenticate(user) {
        this.setState({
            user: user
        });

        // updating user's details
        localStorage.setItem(config.localStorageKey, JSON.stringify(user));
    }

    render() {
        return (
            <Switch>
                <Route exact path='/' component={Home} />
                <Route exact path='/login' render={() => <Login authenticate={this.authenticate} />} />
                <Route exact path='/signup' render={() => <Signup authenticate={this.authenticate} />} />
                <Route path='/dashboard' render={() => (
                    this.state.user.isLoggedIn ? 
                            (<Dashboard authenticate={this.authenticate} user={this.state.user} />) : 
                            (<Redirect to="/login" />)
                )} />
            </Switch>
        );
    }
} 

Controlla il progetto completo qui: https://github.com/varunon9/hello-react


1

Sembra che la tua esitazione sia nel creare il tuo componente e poi inviare il metodo di rendering? Bene, puoi evitare entrambi usando semplicemente il rendermetodo del <Route>componente. Non è necessario creare un <AuthenticatedRoute>componente a meno che non lo si desideri davvero. Può essere semplice come di seguito. Prendi nota della {...routeProps}diffusione assicurandoti di continuare a inviare le proprietà del <Route>componente al componente figlio ( <MyComponent>in questo caso).

<Route path='/someprivatepath' render={routeProps => {

   if (!this.props.isLoggedIn) {
      this.props.redirectToLogin()
      return null
    }
    return <MyComponent {...routeProps} anotherProp={somevalue} />

} />

Consulta la documentazione di rendering di React Router V4

Se desideri creare un componente dedicato, sembra che tu sia sulla strada giusta. Dato che React Router V4 è un instradamento puramente dichiarativo (lo dice proprio nella descrizione), non credo che te la caverai mettendo il tuo codice di reindirizzamento al di fuori del normale ciclo di vita dei componenti. Guardando il codice per React Router stesso , eseguono il reindirizzamento in uno componentWillMounto in componentDidMountbase al fatto che sia o meno il rendering lato server. Ecco il codice seguente, che è piuttosto semplice e potrebbe aiutarti a sentirti più a tuo agio con dove mettere la logica di reindirizzamento.

import React, { PropTypes } from 'react'

/**
 * The public API for updating the location programatically
 * with a component.
 */
class Redirect extends React.Component {
  static propTypes = {
    push: PropTypes.bool,
    from: PropTypes.string,
    to: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.object
    ])
  }

  static defaultProps = {
    push: false
  }

  static contextTypes = {
    router: PropTypes.shape({
      history: PropTypes.shape({
        push: PropTypes.func.isRequired,
        replace: PropTypes.func.isRequired
      }).isRequired,
      staticContext: PropTypes.object
    }).isRequired
  }

  isStatic() {
    return this.context.router && this.context.router.staticContext
  }

  componentWillMount() {
    if (this.isStatic())
      this.perform()
  }

  componentDidMount() {
    if (!this.isStatic())
      this.perform()
  }

  perform() {
    const { history } = this.context.router
    const { push, to } = this.props

    if (push) {
      history.push(to)
    } else {
      history.replace(to)
    }
  }

  render() {
    return null
  }
}

export default Redirect

1

La mia risposta precedente non è scalabile. Ecco quello che penso sia un buon approccio-

I tuoi percorsi

<Switch>
  <Route
    exact path="/"
    component={matchStateToProps(InitialAppState, {
      routeOpen: true // no auth is needed to access this route
    })} />
  <Route
    exact path="/profile"
    component={matchStateToProps(Profile, {
      routeOpen: false // can set it false or just omit this key
    })} />
  <Route
    exact path="/login"
    component={matchStateToProps(Login, {
      routeOpen: true
    })} />
  <Route
    exact path="/forgot-password"
    component={matchStateToProps(ForgotPassword, {
      routeOpen: true
    })} />
  <Route
    exact path="/dashboard"
    component={matchStateToProps(DashBoard)} />
</Switch>

L'idea è di utilizzare un wrapper in componentprops che restituirebbe il componente originale se non è richiesta l'autenticazione o già autenticato altrimenti restituirebbe il componente predefinito, ad esempio Login.

const matchStateToProps = function(Component, defaultProps) {
  return (props) => {
    let authRequired = true;

    if (defaultProps && defaultProps.routeOpen) {
      authRequired = false;
    }

    if (authRequired) {
      // check if loginState key exists in localStorage (Your auth logic goes here)
      if (window.localStorage.getItem(STORAGE_KEYS.LOGIN_STATE)) {
        return <Component { ...defaultProps } />; // authenticated, good to go
      } else {
        return <InitialAppState { ...defaultProps } />; // not authenticated
      }
    }
    return <Component { ...defaultProps } />; // no auth is required
  };
};

se l'autenticazione non è richiesta, non passare il componente alla funzione matchStateToProps, con ciò eliminerai la necessità del flag routeOpen
Dheeraj

1

Ecco il semplice percorso pulito e protetto

const ProtectedRoute 
  = ({ isAllowed, ...props }) => 
     isAllowed 
     ? <Route {...props}/> 
     : <Redirect to="/authentificate"/>;
const _App = ({ lastTab, isTokenVerified })=> 
    <Switch>
      <Route exact path="/authentificate" component={Login}/>
      <ProtectedRoute 
         isAllowed={isTokenVerified} 
         exact 
         path="/secrets" 
         component={Secrets}/>
      <ProtectedRoute 
         isAllowed={isTokenVerified} 
         exact 
         path="/polices" 
         component={Polices}/>
      <ProtectedRoute 
         isAllowed={isTokenVerified} 
         exact 
         path="/grants" component={Grants}/>
      <Redirect from="/" to={lastTab}/>
    </Switch>

isTokenVerified è una chiamata al metodo per controllare il token di autorizzazione fondamentalmente restituisce booleano.


Questa è l'unica soluzione qui che ho trovato funzionante se stai passando un componente o bambini al percorso.
Shawn

Nota: ho appena chiamato il mio isTokenVerified () nella mia funzione ProtectedRoute e non ho avuto bisogno di passare il prop isAllowed su tutte le rotte.
Shawn

1

Ecco come l'ho risolto con React e Typescript. Spero che sia d'aiuto !

import * as React from 'react';
import { Route, RouteComponentProps, RouteProps, Redirect } from 'react-router';

const PrivateRoute: React.SFC<RouteProps> = ({ component: Component, ...rest }) => {
    if (!Component) {
      return null;
    }
    const isLoggedIn = true; // Add your provider here
    return (
      <Route
        {...rest}
            render={(props: RouteComponentProps<{}>) => isLoggedIn ? (<Component {...props} />) : (<Redirect to={{ pathname: '/', state: { from: props.location } }} />)}
      />
    );
  };

export default PrivateRoute;








<PrivateRoute component={SignIn} path="/signin" />


0
const Root = ({ session }) => {
  const isLoggedIn = session && session.getCurrentUser
  return (
    <Router>
      {!isLoggedIn ? (
        <Switch>
          <Route path="/signin" component={<Signin />} />
          <Redirect to="/signin" />
        </Switch>
      ) : (
        <Switch>
          <Route path="/" exact component={Home} />
          <Route path="/about" component={About} />
          <Route path="/something-else" component={SomethingElse} />
          <Redirect to="/" />
        </Switch>
      )}
    </Router>
  )
}

0

Cercavo anche una risposta. Qui tutte le risposte sono abbastanza buone, ma nessuna di esse fornisce risposte su come possiamo usarla se l'utente avvia l'applicazione dopo averla riaperta. (Volevo dire usando i cookie insieme).

Non è necessario creare nemmeno un componente privateRoute diverso. Di seguito è il mio codice

    import React, { Component }  from 'react';
    import { Route, Switch, BrowserRouter, Redirect } from 'react-router-dom';
    import { Provider } from 'react-redux';
    import store from './stores';
    import requireAuth from './components/authentication/authComponent'
    import SearchComponent from './components/search/searchComponent'
    import LoginComponent from './components/login/loginComponent'
    import ExampleContainer from './containers/ExampleContainer'
    class App extends Component {
    state = {
     auth: true
    }


   componentDidMount() {
     if ( ! Cookies.get('auth')) {
       this.setState({auth:false });
     }
    }
    render() {
     return (
      <Provider store={store}>
       <BrowserRouter>
        <Switch>
         <Route exact path="/searchComponent" component={requireAuth(SearchComponent)} />
         <Route exact path="/login" component={LoginComponent} />
         <Route exact path="/" component={requireAuth(ExampleContainer)} />
         {!this.state.auth &&  <Redirect push to="/login"/> }
        </Switch>
       </BrowserRouter>
      </Provider>);
      }
     }
    }
    export default App;

Ed ecco authComponent

import React  from 'react';
import { withRouter } from 'react-router';
import * as Cookie from "js-cookie";
export default function requireAuth(Component) {
class AuthenticatedComponent extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   auth: Cookie.get('auth')
  }
 }
 componentDidMount() {
  this.checkAuth();
 }
 checkAuth() {
  const location = this.props.location;
  const redirect = location.pathname + location.search;
  if ( ! Cookie.get('auth')) {
   this.props.history.push(`/login?redirect=${redirect}`);
  }
 }
render() {
  return Cookie.get('auth')
   ? <Component { ...this.props } />
   : null;
  }
 }
 return  withRouter(AuthenticatedComponent)
}

Di seguito ho scritto sul blog, puoi ottenere spiegazioni più approfondite anche lì.

Crea percorsi protetti in ReactJS


0

La soluzione che alla fine ha funzionato meglio per la mia organizzazione è descritta di seguito, aggiunge solo un controllo sul rendering per la rotta sysadmin e reindirizza l'utente a un diverso percorso principale dell'applicazione se non è autorizzato a essere nella pagina.

SysAdminRoute.tsx

import React from 'react';
import { Route, Redirect, RouteProps } from 'react-router-dom';
import AuthService from '../services/AuthService';
import { appSectionPageUrls } from './appSectionPageUrls';
interface IProps extends RouteProps {}
export const SysAdminRoute = (props: IProps) => {
    var authService = new AuthService();
    if (!authService.getIsSysAdmin()) { //example
        authService.logout();
        return (<Redirect to={{
            pathname: appSectionPageUrls.site //front-facing
        }} />);
    }
    return (<Route {...props} />);
}

Ci sono 3 percorsi principali per la nostra implementazione, il sito / pubblico, il client / app connesso e gli strumenti di amministrazione di sys in / sysadmin. Vieni reindirizzato in base alla tua "autenticità" e questa è la pagina su / sysadmin.

SysAdminNav.tsx

<Switch>
    <SysAdminRoute exact path={sysadminUrls.someSysAdminUrl} render={() => <SomeSysAdminUrl/> } />
    //etc
</Switch>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.