¿Cómo implementar rutas autenticadas en React Router 4?

122

Estaba tratando de implementar rutas autenticadas, pero descubrí que React Router 4 ahora evita que esto funcione:

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

El error es:

Advertencia: No debe utilizar <Route component>y <Route children>en la misma ruta; <Route children>será ignorado

En ese caso, ¿cuál es la forma correcta de implementar esto?

Aparece en react-routerdocumentos (v4), sugiere algo como

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

Pero, ¿es posible lograr esto agrupando un montón de rutas?


ACTUALIZAR

Ok, después de investigar un poco, se me ocurrió esto:

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
}

Es correcto enviar una acción en render()él se siente mal. ¿Realmente no parece correcto con componentDidMounto con algún otro gancho tampoco?

Jiew Meng
fuente
es mejor hacerlo en componetWillMount si no se utiliza la representación del lado del servidor.
mfahadi
@mfahadi, gracias por la entrada. Todavía no estoy usando SSR, pero si quiero usarlo en el futuro, ¿lo mantengo en render? Además, si el usuario es redirigido componentWillMount, ¿alguna vez podrá ver la salida renderizada incluso por una fracción de segundo?
Jiew Meng
Lamento mucho decir que componentWillMount()no se llama en SSR, es componentDidMount()que no se llama. como componentWillMount()se llamó antes render(), por lo que el usuario no verá nada del componente nuevo. por lo que es el mejor lugar para buscar.
mfahadi
1
podría usar el <Redirect to="/auth"> de los documentos en lugar de llamar a la acción de envío
Fuzail l'Corder

Respuestas:

238

Vas a querer usar el Redirectcomponente. Hay algunos enfoques diferentes para este problema. Aquí hay uno que me gusta, tiene un componente PrivateRoute que toma un authedaccesorio y luego se renderiza en función de ese accesorio.

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

Ahora tu Routes puede verse algo como esto

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

Si todavía está confundido, escribí esta publicación que puede ayudar: rutas protegidas y autenticación con React Router v4

Tyler McGinnis
fuente
2
Oh, esto es similar a mi solución, pero usa <Redirect />. ¿El problema es <Redirect />que no parece funcionar con redux en mi caso? Necesito enviar una acción
Jiew Meng
3
No sé por qué, pero agregar state: {from: props.location}}}causó un maximum call stack exceeded. Tuve que quitarlo. ¿Podrías explicar por qué esta opción es útil @Tyler McGinnis?
Martpie
@KeitIG ​​Eso es extraño. Es útil porque te dice de dónde vienes. Un ejemplo sería si quisiera que el usuario se autenticara y, una vez que se autentique, llévelo de regreso a la página a la que intentaba acceder antes de redirigirlo.
Tyler McGinnis
6
@faraz Esto explica la ({component: Component, ...rest})sintaxis. ¡Tenía la misma pregunta lol! stackoverflow.com/a/43484565/6502003
protoEvangelion
2
@TylerMcGinnis ¿Qué pasa si necesitamos usar la función de render para pasar accesorios al componente?
C Bauer
16

Tnx Tyler McGinnis por una solución. Hago mi idea a partir de la idea de Tyler McGinnis.

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

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

Puedes implementar eso así

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

decisionFunc solo una función que devuelve verdadero o falso

const redirectStart = props => <Redirect to="/orders" />
MrDuDuDu
fuente
8

(Usando Redux para la gestión del estado)

Si el usuario intenta acceder a cualquier URL, primero voy a verificar si el token de acceso está disponible, si no lo redirigir a la página de inicio de sesión, una vez que el usuario inicia sesión usando la página de inicio de sesión, lo almacenamos en el almacenamiento local así como en nuestro estado redux. (almacenamiento local o cookies ... mantenemos este tema fuera de contexto por ahora).
ya que el estado de redux como actualizado y las rutas privadas se volverán a generar. ahora tenemos token de acceso, así que lo redireccionaremos a la página de inicio.

Almacene los datos de carga útil de autorización decodificados también en estado redux y páselos al contexto de reacción. (No tenemos que usar el contexto, pero para acceder a la autorización en cualquiera de nuestros componentes secundarios anidados, es fácil acceder desde el contexto en lugar de conectar todos y cada uno de los componentes secundarios a redux).

Se puede acceder a todas las rutas que no necesitan roles especiales directamente después de iniciar sesión. Si necesita un rol como administrador (hicimos una ruta protegida que verifica si tenía el rol deseado o si no se redirige a un componente no autorizado)

de manera similar en cualquiera de sus componentes si tiene que deshabilitar el botón o algo basado en el rol.

simplemente puedes hacerlo de esta manera

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>

Entonces, ¿qué pasa si el usuario intenta insertar un token ficticio en localstorage? Como tenemos token de acceso, lo redireccionaremos al componente de inicio. Mi componente de inicio hará una llamada de descanso para obtener datos, ya que el token jwt era ficticio, la llamada de descanso devolverá al usuario no autorizado. Así que llamo al cierre de sesión (que borrará el almacenamiento local y redirigirá a la página de inicio de sesión nuevamente). Si la página de inicio tiene datos estáticos y no realiza ninguna llamada de API (entonces debe tener una llamada de API de verificación de token en el backend para que pueda verificar si el token es REAL antes de cargar la página de inicio)

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

MUESTRA DE TOKEN JWT DECODIFICADO

{
  "authorization": {
    "roles": [
      "admin",
      "operator"
    ]
  },
  "exp": 1591733170,
  "user_id": 1,
  "orig_iat": 1591646770,
  "email": "hemanthvrm@stackoverflow",
  "username": "hemanthvrm"
}
Hemantvrm
fuente
¿Y cómo maneja el acceso directo a Signin? Si un usuario sabe que no ha iniciado sesión, debería tener la opción de acceder directamente al inicio de sesión, ¿verdad?
Carkod
@carkod ... De forma predeterminada, si intenta acceder a cualquier ruta, será redirigido a la página de inicio de sesión ... (ya que no tendrá token)
Hemanthvrm
@carkod ... una vez que el usuario hizo clic en cerrar sesión o de lo contrario mi token de actualización jwt expira ... llamo a la función de cierre de sesión donde borro el almacenamiento local y la ventana de actualización ... por lo tanto, el almacenamiento local no tendrá el token ... se redirigirá automáticamente a la página de inicio de sesión
Hemanthvrm
Tengo una versión mejor para aquellos que usan redux ... actualizaré mi respuesta en un par de días ... gracias -
Hemanthvrm
3

instalar react-router-dom

luego cree dos componentes, uno para usuarios válidos y otro para usuarios inválidos.

prueba esto en 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;
José G Varanam
fuente
4
¿Por ruta? Esto no escalará.
Jim G.
3

Basado en la respuesta de @Tyler McGinnis . Hice un enfoque diferente usando la sintaxis de ES6 y rutas anidadas con componentes envueltos:

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

Y usándolo:

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

    <Route exact path='/' component={PublicHomePage} />
  </div>
</BrowserRouter>
Felipe Augusto
fuente
2

Sé que ha pasado un tiempo, pero he estado trabajando en un paquete npm para rutas públicas y privadas.

Aquí se explica cómo hacer una ruta privada:

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

Y también puede hacer rutas públicas a las que solo pueden acceder los usuarios no autorizados

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

¡Espero que ayude!

Gonzalo Cañada
fuente
¿Puede proporcionar más ejemplos que incluyan todas las importaciones y envolturas, por ejemplo, en 2 rutas públicas, 2 rutas privadas y 2 PropsRoute, en el App.js principal? gracias
MH
2

Implementé usando-

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

Los accesorios de autenticación se pasarán a los componentes, por ejemplo, el registro con el que se puede cambiar el estado del usuario. AppRoutes completas

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

Consulta el proyecto completo aquí: https://github.com/varunon9/hello-react

Varun Kumar
fuente
1

¿Parece que su duda es crear su propio componente y luego enviarlo en el método de renderizado? Bueno, puedes evitar ambos con solo usar el rendermétodo del <Route>componente. No es necesario crear un <AuthenticatedRoute>componente a menos que realmente lo desee. Puede ser tan simple como a continuación. Tenga en cuenta la {...routeProps}extensión asegurándose de continuar enviando las propiedades del <Route>componente al componente secundario ( <MyComponent>en este caso).

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

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

} />

Consulte la documentación de renderización de React Router V4

Si desea crear un componente dedicado, parece que está en el camino correcto. Dado que React Router V4 es un enrutamiento puramente declarativo (lo dice bien en la descripción), no creo que se salga con la suya poniendo su código de redireccionamiento fuera del ciclo de vida normal del componente. Mirando el código para React Router en sí , realizan la redirección en cualquiera de los dos componentWillMounto componentDidMountdependiendo de si se trata de una representación del lado del servidor. Aquí está el código a continuación, que es bastante simple y puede ayudarlo a sentirse más cómodo con dónde colocar su lógica de redirección.

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
Todd Chaffee
fuente
1

Mi respuesta anterior no es escalable. Esto es lo que creo que es un buen enfoque:

Tus rutas

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

La idea es usar un contenedor en los componentaccesorios que devolvería el componente original si no se requiere autenticación o si ya está autenticado, de lo contrario, devolvería el componente predeterminado, por ejemplo, Iniciar sesión.

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
  };
};
Varun Kumar
fuente
si no se requiere autenticación, no pase el componente a la función matchStateToProps, con eso eliminaría la necesidad de la bandera routeOpen
Dheeraj
1

Aquí está la ruta protegida limpia simple

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 es una llamada a un método para verificar el token de autorización, básicamente, devuelve un valor booleano.

Anupam Maurya
fuente
Esta es la única solución aquí que encontré que funciona si está pasando un componente o elementos secundarios a la ruta.
Shawn
Nota: Acabo de llamar a mi isTokenVerified () en mi función ProtectedRoute y no necesitaba pasar la propiedad isAllowed en todas las rutas.
Shawn
1

Así es como lo resolví con React y Typecript. Espero eso ayude !

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" />

Max_Thom
fuente
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>
  )
}
Compañero extraño
fuente
0

También estaba buscando alguna respuesta. Aquí todas las respuestas son bastante buenas, pero ninguna de ellas da respuestas sobre cómo podemos usarla si el usuario inicia la aplicación después de abrirla. (Quise decir usar cookies juntos).

No es necesario crear ni siquiera un componente privateRoute diferente. Abajo está mi código

    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;

Y aquí está 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)
}

A continuación, escribí un blog, también puede obtener una explicación más detallada allí.

Crear rutas protegidas en ReactJS

nirmal
fuente
0

La solución que finalmente funcionó mejor para mi organización se detalla a continuación, solo agrega una verificación en el renderizado para la ruta del administrador del sistema y redirige al usuario a una ruta principal diferente de la aplicación si no se les permite estar en la página.

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

Hay 3 rutas principales para nuestra implementación, el público / sitio, el cliente / aplicación que ha iniciado sesión y las herramientas de administración del sistema en / sysadmin. Se le redirige en función de su 'autorización' y esta es la página en / sysadmin.

SysAdminNav.tsx

<Switch>
    <SysAdminRoute exact path={sysadminUrls.someSysAdminUrl} render={() => <SomeSysAdminUrl/> } />
    //etc
</Switch>
C Bauer
fuente