[javascript] react-router에서 경로에 대한 액세스를 제한하는 방법은 무엇입니까?

누구든지 react-router에서 특정 경로에 대한 액세스를 제한하는 방법을 알고 있습니까? 특정 경로에 대한 액세스를 허용하기 전에 사용자가 로그인했는지 확인하고 싶습니다. 간단 할 거라고 생각했지만 문서에 방법이 명확하지 않습니다.

<Route>구성 요소를 정의 할 때 설정 해야합니까, 아니면 구성 요소 처리기 내에서 처리해야합니까?

<Route handler={App} path="/">
  <NotFoundRoute handler={NotFound} name="not-found"/>
  <DefaultRoute handler={Login} name="login"/>
  <Route handler={Todos} name="todos"/> {/* I want this to be restricted */}
</Route>



답변

업데이트 (2019 년 8 월 16 일)

react-router v4에서 React Hooks를 사용하면 약간 다르게 보입니다. 의 당신의 시작하자 App.js.

export default function App() {
  const [isAuthenticated, userHasAuthenticated] = useState(false);

  useEffect(() => {
    onLoad();
  }, []);

  async function onLoad() {
    try {
      await Auth.currentSession();
      userHasAuthenticated(true);
    } catch (e) {
      alert(e);
    }
  }

  return (
    <div className="App container">
      <h1>Welcome to my app</h1>
      <Switch>
        <UnauthenticatedRoute
          path="/login"
          component={Login}
          appProps={{ isAuthenticated }}
        />
        <AuthenticatedRoute
          path="/todos"
          component={Todos}
          appProps={{ isAuthenticated }}
        />
        <Route component={NotFound} />
      </Switch>
    </div>
  );
}

Auth사용자가 현재 인증되었는지 확인하기 위해 라이브러리를 사용하고 있습니다. 이것을 인증 확인 기능으로 대체하십시오. 그렇다면 isAuthenticated플래그를로 설정합니다 true. 앱이 처음로드 될 때이 작업을 수행합니다. 또한 언급 할 가치가있는 것은 인증 확인이 실행되는 동안 앱에로드 기호를 추가 할 수 있으므로 페이지를 새로 고칠 때마다 로그인 페이지를 플래시하지 않습니다.

그런 다음 깃발을 경로에 전달합니다. 두 가지 유형의 경로 AuthenticatedRouteUnauthenticatedRoute.

AuthenticatedRoute.js모습이 맘에.

export default function AuthenticatedRoute({ component: C, appProps, ...rest }) {
  return (
    <Route
      {...rest}
      render={props =>
        appProps.isAuthenticated
          ? <C {...props} {...appProps} />
          : <Redirect
              to={`/login?redirect=${props.location.pathname}${props.location.search}`}
            />}
    />
  );
}

가로 isAuthenticated설정되어 있는지 확인합니다 true. 그렇다면 원하는 구성 요소를 렌더링합니다. 그렇지 않은 경우 로그인 페이지로 리디렉션됩니다.

UnauthenticatedRoute.js다른 한편으로는 다음과 같습니다.

export default ({ component: C, appProps, ...rest }) =>
  <Route
    {...rest}
    render={props =>
      !appProps.isAuthenticated
        ? <C {...props} {...appProps} />
        : <Redirect to="/" />}
  />;

이 경우 isAuthenticated가로 설정되어 있으면 false원하는 구성 요소를 렌더링합니다. true로 설정하면 홈페이지로 이동합니다.

자세한 버전은 당사 가이드 ( https://serverless-stack.com/chapters/create-a-route-that-redirects.html) 에서 찾을 수 있습니다 .

이전 버전

허용되는 답변은 맞지만 Mixins는 React 팀에 의해 유해한 것으로 간주됩니다 ( https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html ).

누군가이 질문을 발견하고 권장되는 방법을 찾고 있다면 Mixins 대신 Higher Order Components를 사용하는 것이 좋습니다.

다음은 계속하기 전에 사용자가 로그인했는지 확인하는 HOC의 예입니다. 사용자가 로그인하지 않은 경우 로그인 페이지로 리디렉션됩니다. 이 구성 요소 isLoggedIn는 기본적으로 사용자가 로그인했는지 여부를 나타 내기 위해 응용 프로그램에서 저장할 수있는 플래그 인 라는 prop을받습니다 .

import React from 'react';
import { withRouter } from 'react-router';

export default function requireAuth(Component) {

  class AuthenticatedComponent extends React.Component {

    componentWillMount() {
      this.checkAuth();
    }

    checkAuth() {
      if ( ! this.props.isLoggedIn) {
        const location = this.props.location;
        const redirect = location.pathname + location.search;

        this.props.router.push(`/login?redirect=${redirect}`);
      }
    }

    render() {
      return this.props.isLoggedIn
        ? <Component { ...this.props } />
        : null;
    }

  }

  return withRouter(AuthenticatedComponent);
}

그리고이 HOC를 사용하려면 경로를 감싸십시오. 귀하의 예의 경우 다음과 같습니다.

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

여기에있는 자세한 단계별 자습서 ( https://serverless-stack.com/chapters/create-a-hoc-that-checks-auth.html) 에서이 항목과 몇 가지 다른 주제를 다룹니다.


답변

React Router 4의 문서에 이에 대한 예가 있습니다. Redirect

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

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


답변

react-router 라우터에 대한 선언적 접근 방식을 권장합니다. 라우터를 가능한 한 멍청하게 만들고 구성 요소에 라우팅 논리를 넣지 않도록해야합니다.

방법은 다음과 같습니다 ( loggedIn소품 을 전달한다고 가정 ).

const DumbRouter = ({ loggedIn }) => (
  <Router history={history}>
    <Switch>
      {[
        !loggedIn && LoggedOutRoutes,
        loggedIn && LoggedInRouter,
        <Route component={404Route} />
      ]}
    </Switch>
  </Router>
);

const LoggedInRoutes = [
  <Route path="/" component={Profile} />
];

const LoggedOutRoutes = [
  <Route path="/" component={Login} />
];


답변

전체 애플리케이션에서 인증을 사용하려면 애플리케이션 전체에 일부 데이터 (예 : 토큰)를 저장해야합니다. $auth객체 관리를 담당하는 두 개의 React mixin을 설정할 수 있습니다 . 이 개체는 두 믹스 인 외부에서 사용할 수 없습니다. 그 예는 다음과 같습니다.

define('userManagement', function() {
    'use strict';

    var $auth = {
        isLoggedIn: function () {
            // return something, e.g. using server-stored data
        }
    };

    return {
        Authenticator: {
           login: function(username, password) {
               // modify $auth object, or call server, or both
           }
        },

        NeedsAuthenticatedUser: {
            statics: {
                willTransitionTo: function (transition) {
                    if (!$auth.isLoggedIn()) {
                        transition.abort();
                    }
                }
            }
        }
    };
});

그런 다음 Authenticator로그인 구성 요소 (로그인 화면, 로그인 팝업 등)에 믹싱을 혼합하고 this.login필요한 모든 데이터가 있으면 함수를 호출 할 수 있습니다.

가장 중요한 것은 NeedsAuthenticatedUsermixin 을 혼합하여 구성 요소를 보호하는 것입니다 . 인증 된 사용자가 필요한 각 구성 요소는 다음과 같아야합니다.

var um = require('userManagement');

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

하는 것으로 NeedsAuthenticatedUser사용이 반응 라우터의 API ( willTransitionTotransition.abort()).


답변

HOC를 사용할 수 있으며 auth는 true 또는 false 값을 변경할 수있는 변수입니다 (권한 부여).

<Route path="/login" component={SignIn} />
<Route path="/posts" render = {() => (auth ?  (<Post />) : (<Redirect to="/login" />))}/>


답변

private-route.tsx

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

interface PrivateRouteProps extends RouteProps {
  /**
   * '/login' for example.
   */
  redirectTo: string;

  /**
   * If true, won't redirect.
   * We are using a function instead of a bool, a bool does not seem to be updated
   * after having successfully authenticated.
   */
  isLogged: () => boolean;
}


export function PrivateRoute(props: PrivateRouteProps) {
  // `component: Component` is not typing, it assign the value to a new variable.
  let { isLogged, redirectTo, component: Component, ...rest }: any = props;

  // error: JSX type element Component does not have call signature or ... AVOIDED BY ADDING ANY, still work,
  // and did not find a proper way to fix it.
  return <Route {...rest} render={(props) => (
    isLogged()
      ? <Component {...props}/>
      : <Redirect to={{
        pathname: redirectTo,
        state: { from: props.location }
      }} />
  )} />;
}

용법:

        <PrivateRoute exact={true}
                      path="/admin/"
                      redirectTo={'/admin/login'}
                      isLogged={this.loginService.isLogged}
                      component={AdminDashboardPage}/>
        <Route path="/admin/login/" component={AdminLoginPage}/>

https://tylermcginnis.com/react-router-protected-routes-authentication/ 기반 .


답변

일반적으로 로그인 한 사용자에게는 토큰이 부여되며 서버와의 모든 통신에이 토큰을 사용합니다. 우리가 일반적으로하는 일은 루트 페이지를 정의하는 것이며, 그 페이지 위에 모든 것이 구축됩니다. 이 루트 페이지는 현지화, 인증 및 기타 구성을 수행합니다.

여기에 예가 있습니다

Routes = (
    <Route path="/" handler={Root}>
        <Route name="login" handler={Login} />
        <Route name="forget" handler={ForgetPassword} />
        <Route handler={Main} >
            <Route name="overview" handler={Overview} />
            <Route name="profile" handler={Profile} />
            <DefaultRoute handler={Overview} />
        </Route>
        <DefaultRoute handler={Login} />
        <NotFoundRoute handler={NotFound} />
    </Route>
);

루트 페이지에서 토큰 null을 확인하거나 서버에서 토큰을 인증하여 사용자가 유효한 로그인인지 확인하십시오.

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