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 난 레코더와

답변:


239

Redirect컴포넌트 를 사용하고 싶을 것 입니다. 이 문제에 대한 몇 가지 접근 방식이 있습니다. 여기 내가 좋아하는 것이 있는데, authed소품을 받아 그 소품을 기반으로 렌더링 하는 PrivateRoute 구성 요소가 있습니다.

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

이제 당신 Route은 다음과 같이 보일 수 있습니다.

<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 />내 경우 redux에서 작동하지 않는 것 같습니다. 나는 액션 파견 할 필요가
Jiew 멩

3
이유는 모르겠지만 추가 state: {from: props.location}}}하면 maximum call stack exceeded. 나는 그것을 제거해야했다. 이 옵션이 왜 유용한 지 설명해 주시겠습니까 @Tyler McGinnis?
martpie

@KeitIG ​​이상합니다. 어디에서 왔는지 알려주기 때문에 유용합니다. 예를 들어 사용자가 인증하기를 원하는 경우 사용자가 인증되면 리디렉션하기 전에 액세스하려고했던 페이지로 다시 이동합니다.
타일러 McGinnis

6
@faraz 이것은 ({component: Component, ...rest})구문을 설명 합니다. 저도 같은 질문을 받았습니다. stackoverflow.com/a/43484565/6502003
protoEvangelion 2017

2
@TylerMcGinnis 컴포넌트에 props를 전달하기 위해 render 함수를 사용해야한다면 어떨까요?
C Bauer

16

Tnx Tyler McGinnis가 솔루션을 제공합니다. 나는 Tyler McGinnis 아이디어에서 내 아이디어를 만듭니다.

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

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

다음과 같이 구현할 수 있습니다.

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

DecisionFunc는 true 또는 false를 반환하는 함수입니다.

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

8

(상태 관리를 위해 Redux 사용)

사용자가 URL에 액세스하려고하면 먼저 액세스 토큰을 사용할 수 있는지 확인하고 로그인 페이지로 리디렉션하지 않으면 사용자가 로그인 페이지를 사용하여 로그인하면 redux 상태뿐만 아니라 localstorage에 저장합니다. (localstorage 또는 cookies .. 지금은이 주제를 컨텍스트에서 제외).
redux 상태가 업데이트되고 privateroutes가 다시 렌더링되기 때문입니다. 이제 액세스 토큰이 있으므로 홈페이지로 리디렉션합니다.

디코딩 된 권한 부여 페이로드 데이터도 redux 상태에 저장하고이를 반응 컨텍스트에 전달합니다. (컨텍스트를 사용할 필요는 없지만 중첩 된 자식 구성 요소의 권한에 액세스하려면 각 자식 구성 요소를 redux에 연결하는 대신 컨텍스트에서 쉽게 액세스 할 수 있습니다.)

특별한 역할이 필요하지 않은 모든 라우트는 로그인 후 바로 접근 할 수 있습니다 .. 관리자와 같은 역할이 필요한 경우 (권한이없는 컴포넌트로 리디렉션하지 않으면 원하는 역할을 가지고 있는지 확인하는 보호 경로를 만들었습니다)

버튼이나 역할에 따라 비활성화해야하는 경우 모든 구성 요소에서 유사하게.

단순히 이런 식으로 할 수 있습니다

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 토큰이 더미이기 때문에 나머지 호출을 수행하여 데이터를 가져옵니다. 나머지 호출은 권한이없는 사용자를 반환합니다. 그래서 나는 로그 아웃을 호출합니다 (localstorage를 지우고 로그인 페이지로 다시 리디렉션됩니다). 홈페이지에 정적 데이터가 있고 API 호출을하지 않는 경우 (홈페이지를로드하기 전에 토큰이 REAL인지 확인할 수 있도록 백엔드에 token-verify 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 토큰 샘플

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

그리고 직접 액세스를 Signin어떻게 처리 합니까? 사용자가 자신이 로그인하지 않은 것을 알고 있다면 로그인에 직접 액세스 할 수있는 옵션이 있어야합니다.
carkod

@carkod ... 그가 어떤 경로를 액세스하려고하면, 그는 로그인 페이지로 리디렉션됩니다 기본적으로 (그는 토큰을 갖는 습관 때문에)
Hemanthvrm

@carkod .. 사용자가 로그 아웃을 클릭하거나 그렇지 않으면 내 jwt 새로 고침 토큰이 만료되면 ..i는 localstorage를 지우고 창을 새로 고치는 로그 아웃 기능을 호출합니다. 따라서 localstorage에 토큰이 없습니다.. 자동으로 로그인 페이지로 리디렉션됩니다.
Hemanthvrm

나는 redux를 사용하는 사람들을 위해 더 나은 버전을 가지고 있습니다 .. 며칠 안에 내 대답을 업데이트합니다.
감사합니다

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
경로당? 이것은 확장되지 않습니다.
Jim G.

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

도움이 되었기를 바랍니다.


예를 들어 메인 App.js의 2 개의 publicroutes, 2 개의 private route 및 2 개의 PropsRoute에서 모든 가져 오기 및 랩을 포함하여 더 많은 예제를 제공 할 수 있습니까? 감사합니다
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 메서드에서 디스패치하는 데 주저하는 것 같습니다. 구성 요소 의 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는 순전히 선언적 라우팅 이기 때문에 (설명에서 그렇게 말하고 있습니다) 정상적인 구성 요소 수명주기 외부에 리디렉션 코드를 두는 것으로 벗어나지 않을 것이라고 생각합니다. 상기 찾고 라우터 자체에 대한 코드 반응 , 그들은에서 리디렉션을 수행하거나 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인증이 필요하지 않거나 이미 인증 된 경우 원래 구성 요소를 반환하는 props 에서 래퍼를 사용하는 것입니다. 그렇지 않으면 로그인과 같은 기본 구성 요소를 반환합니다.

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

당신이 routeOpen 플래그에 대한 필요성을 제거하는 것입니다 그와 함께 인증은 matchStateToProps 함수에 다음 해달라고 패스 구성 요소를 필요하지 않은 경우
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 인증 토큰을 확인하는 메서드 호출입니다. 기본적으로 부울을 반환합니다.


이것은 컴포넌트 또는 자식을 경로에 전달하는 경우 작동하는 유일한 해결책입니다.
Shawn

참고 : 방금 ProtectedRoute 함수에서 isTokenVerified ()을 호출했으며 모든 경로에서 isAllowed 소품을 전달할 필요가 없었습니다.
Shawn

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

나는 또한 몇 가지 대답을 찾고 있었다. 여기에서 모든 답변은 꽤 좋지만 사용자가 응용 프로그램을 다시 연 후 시작하면 사용할 수있는 방법에 대한 답변은 없습니다. (쿠키를 함께 사용하는 것을 의미했습니다).

다른 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 가지 주요 경로가 있습니다. 공개 대상 / site, 로그인 한 클라이언트 / app 및 / sysadmin에있는 sys 관리 도구입니다. '인증'에 따라 리디렉션되며 이것은 / sysadmin의 페이지입니다.

SysAdminNav.tsx

<Switch>
    <SysAdminRoute exact path={sysadminUrls.someSysAdminUrl} render={() => <SomeSysAdminUrl/> } />
    //etc
</Switch>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.