Як реалізувати автентифіковані маршрути в React Router 4?


122

Я намагався реалізувати автентифіковані маршрути, але виявив, що React Router 4 зараз заважає цьому працювати:

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

Помилка:

Попередження: не слід використовувати <Route component>і <Route children>в тому ж маршруті; <Route children>буде проігноровано

У такому випадку, який правильний спосіб здійснити це?

Він з'являється у react-router(v4) документах, він пропонує щось подібне

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

Але чи можливо цього досягти, групуючи купу маршрутів разом?


ОНОВЛЕННЯ

Добре, після деяких досліджень я придумав таке:

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
}

Правильно, щоб відправити дію в render()ній не так. Це насправді не здається правильним з componentDidMountчи іншим гачком або?


найкраще робити на componetWillMount, якщо не використовується візуалізація на стороні сервера.
mfahadi

@mfahadi, дякую за вклад. Я ще не використовую SSR, але якщо я хочу використовувати його в майбутньому, чи потрібно це тримати в рендерінгу? Крім того, якщо користувач буде переспрямований componentWillMount, чи зможе він коли-небудь побачити виведений вихід навіть на частку секунди?
Jiew Meng

Мені дуже шкода, що я сказала, що componentWillMount()не вимагається в SSR, це componentDidMount()не називається. як componentWillMount()називалося раніше render(), тому користувач не побачить нічого нового компонента. тому найкраще місце для перевірки.
mfahadi

1
ви можете просто скористатись <Redirect to="/auth"> з документа, а не викликати диспетчерську дію
Fuzail l'Corder

Відповіді:


239

Ви хочете використовувати Redirectкомпонент. Існує кілька різних підходів до цієї проблеми. Ось такий, який мені подобається, є компонент PrivateRoute, який приймає authedопору, а потім надає на основі цього реквізиту.

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

Тепер ваш Routes може виглядати приблизно так

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

Якщо ви все ще плутаєтесь, я написав цю публікацію, яка може допомогти - Захищені маршрути та автентифікація за допомогою React Router v4


2
О, це схоже на моє рішення, але воно використовує <Redirect />. Проблема в тому, <Redirect />що, здається, не працює зі скороченням у моєму випадку? Мені потрібно відправити акцію
Jiew Meng

3
Я не знаю чому, але додавання state: {from: props.location}}}викликало maximum call stack exceeded. Мені довелося її зняти. Чи можете ви пояснити, чому цей варіант корисний @Tyler McGinnis?
март

@KeitIG ​​Це дивно. Це корисно, бо говорить вам, звідки ви прийшли. Прикладом може бути те, якби ви хотіли, щоб користувач пройшов автентифікацію, після того, як вони засвідчать автентифікацію, поверніть їх на сторінку, до якої вони намагалися отримати доступ, перш ніж ви перенаправили їх.
Тайлер МакГінніс

6
@faraz Це пояснює ({component: Component, ...rest})синтаксис. У мене було те саме запитання, хай! stackoverflow.com/a/43484565/6502003
protoEvangelion

2
@TylerMcGinnis Що робити, якщо нам потрібно використовувати функцію візуалізації для передачі реквізиту до компонента?
C Бауер

16

Tnx Тайлер МакГінніс для рішення. Я роблю свою ідею від ідеї Тайлера МакГінніса.

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

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

Ви можете реалізувати це так

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

рішенняFunc просто функція, яка повертає істинне або хибне

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

8

(Використання Redux для управління державою)

Якщо користувач спробує отримати доступ до будь-якого URL-адреси, спершу я перевіряю, чи доступний маркер доступу, якщо він не перенаправлений на сторінку входу. Після того, як користувач увійде в систему, використовуючи сторінку входу, ми зберігаємо це як у локальному сховищі, так і в нашому резервному стані. (локальне зберігання чи файли cookie. Ми поки що не підтримуємо цю тему поза контекстом).
оскільки стан redux як оновлений та privateroutes буде надано. тепер у нас є маркер доступу, тому ми переспрямовуємо на головну сторінку.

Зберігають також декодовані дані корисного навантаження авторизації у зворотному стані та передають їх для реакції на контекст. (Нам не потрібно використовувати контекст, але для доступу до авторизації в будь-якому з вкладених дочірніх компонентів це полегшує доступ із контексту, замість того, щоб підключати кожен дочірній компонент до скорочення).

До всіх маршрутів, які не потребують спеціальних ролей, можна отримати доступ безпосередньо після входу. Якщо йому потрібна така роль, як адміністратор (ми створили захищений маршрут, який перевіряє, чи потрібна йому роль, якщо не перенаправляє на несанкціонований компонент)

аналогічно в будь-якому компоненті, якщо вам доведеться відключити кнопку або щось на основі ролі.

просто ви можете зробити так

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>

Що робити, якщо користувач спробує вставити фіктивний маркер в localstorage. Оскільки у нас є маркер доступу, ми переспрямовуємо на домашній компонент. Мій домашній компонент зробить дзвінок відпочинку для отримання даних, оскільки маркер jwt був фіктивним, виклик відпочинку поверне несанкціонованого користувача. Тож я роблю вихід із виклику (який очистить локальне зберігання та перенаправлення на сторінку входу знову). Якщо домашня сторінка має статичні дані та не здійснює жодних дзвінків api (тоді ви повинні мати підтвердження дзвінка api в бекенді, щоб ви могли перевірити, чи маркер РЕАЛЬНИЙ перед завантаженням домашньої сторінки)

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

ВИЗНАЧЕНИЙ ЗРАЗ JWT TOKEN

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

І як ви звертаєтесь до прямого доступу Signin? Якщо користувач знає, що він не ввійшов, він повинен мати можливість прямого доступу до Signin, правда?
carkod

@carkod ... За замовчуванням, якщо він спробує отримати доступ до будь-якого маршруту, він буде переспрямований на сторінку для входу ... (оскільки він не буде робити маркер)
Hemanthvrm

@carkod .. як тільки користувач натиснув на вихід, інакше мій JWT маркер оновлення закінчується .. я роблю функцію виходу з виклику, де я очищаю локальне зберігання та оновлюю вікно ... отже, локальне зберігання не матиме токен .. воно автоматично автоматичне перенаправлення на сторінку входу
Hemanthvrm

у мене є краща його версія для тих, хто використовує функцію redux..оновлю мою відповідь через пару днів. дякую -
Hemanthvrm

3

встановити react-router-dom

потім створіть два компоненти один для дійсних користувачів та інший для недійсних користувачів.

спробуйте це на 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
За маршрут? Це не буде масштабуватися.
Джим Г.

3

На основі відповіді @Tyler McGinnis . Я зробив інший підхід, використовуючи синтаксис ES6 та вкладені маршрути із загорнутими компонентами:

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

І використовуючи це:

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

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

2

Я знаю, що пройшов час, але я працював над пакетом npm для приватних та громадських маршрутів.

Ось як зробити приватний маршрут:

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

Ви також можете робити загальнодоступні маршрути, до яких може отримати доступ лише несанкціонований користувач

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

Я сподіваюся, що це допомагає!


Чи можете ви надати більше прикладів, включаючи всі імпорти та обгортання, наприклад, у 2 publicroutes, 2 приватних маршрутах та 2 PropsRoute в головному App.js? дякую
MH

2

Я реалізував за допомогою

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

реквізити для автентифікації передаються компонентам, наприклад, реєстрації, за допомогою якої можна змінити стан користувача. Повна AppRoutes-

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

Перевірте повний проект тут: https://github.com/varunon9/hello-react


1

Здається, ваше вагання полягає у створенні власного компонента, а потім диспетчеризації методу візуалізації? Добре ви можете уникнути обох, просто використовуючи renderметод <Route>компонента. Не потрібно створювати <AuthenticatedRoute>компонент, якщо ви цього не хочете. Це може бути так само просто, як нижче. Зверніть увагу на {...routeProps}те, що ви продовжуєте надсилати властивості <Route>компонента до дочірнього компонента ( <MyComponent>у цьому випадку).

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

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

} />

Дивіться документацію щодо надання маршрутизатора React Router V4

Якщо ви хотіли створити виділений компонент, то, схоже, ви на правильному шляху. Оскільки React Router V4 - це суто декларативна маршрутизація (в описі це сказано правильно), я не думаю, що ви увійдете від того, щоб поставити код переадресації поза звичайним життєвим циклом компонентів. Дивлячись на код для самого маршрутизатора React , вони виконують переадресацію componentWillMountабо componentDidMountзалежно від того, чи це серверне відображення чи ні. Ось наведений нижче код, який досить простий і може допомогти вам почуватись зручніше, де розмістити логіку переадресації.

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

Моя попередня відповідь не масштабується. Ось, на мій погляд, хороший підхід -

Ваші маршрути -

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

Ідея полягає у використанні обгортки в componentреквізиті, який би повертав оригінальний компонент, якщо не вимагається автентифікація або вже автентифікована в іншому випадку повертає компонент за замовчуванням, наприклад, 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
  };
};

якщо автентифікація не потрібна, тоді не передайте компонент функції matchStateToProps, за допомогою цього ви усунете необхідність прапора routeOpen
Dheeraj

1

Ось простий чистий захищений маршрут

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 - це виклик методу, щоб перевірити маркер авторизації, в основному він повертає булевий.


Це єдине рішення, з якого я знайшов свою роботу, якщо ви переходите компонент або дітей на маршрут.
Шон

Примітка. Я щойно зателефонував до свого isTokenVerified () у своєму функціоналі ProtectedRoute, і мені не потрібно було передавати опору isAllowed на всіх маршрутах.
Шон

1

Ось як я вирішив це за допомогою React і Typescript. Сподіваюся, це допомагає!

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

Я також шукав певну відповідь. Тут усі відповіді досить хороші, але жодна з них не дає відповідей, як ми можемо ним користуватися, якщо користувач запустить додаток після відкриття його назад. (Я мав на увазі сказати, використовуючи файли cookie разом).

Не потрібно створювати навіть різні компоненти PrivateRoute. Нижче мій код

    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;

І ось 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)
}

Нижче я написав блог, ви також можете отримати більш глибокі пояснення там.

Створіть захищені маршрути в ReactJS


0

Рішення, яке в кращому випадку працює для моєї організації, детально описано нижче, воно просто додає перевірку на візуалізацію маршруту до sysadmin та перенаправляє користувача до іншого основного шляху програми, якщо вони не мають бути на сторінці.

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

Існують 3 основні маршрути для нашої реалізації, спільний доступ до сайту / веб-сайт, вхід у систему клієнт / додаток та інструменти системного адміністрування в / sysadmin. Ви переспрямовуєтесь на основі "автентичності", і це сторінка за адресою / sysadmin.

SysAdminNav.tsx

<Switch>
    <SysAdminRoute exact path={sysadminUrls.someSysAdminUrl} render={() => <SomeSysAdminUrl/> } />
    //etc
</Switch>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.