1. ホーム
  2. javascript

[解決済み] react-routerでルートへのアクセスを制限する方法は?

2022-12-29 01:43:03

質問

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 . これは、アプリが最初にロードされるときに行います。また、ページを更新するたびにログインページが表示されないように、認証チェックが実行されている間はアプリにローディングサインを追加するとよいでしょう。

次に、このフラグをルーティングに渡します。2種類のルーティングを作成します。 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 .

古いバージョン

受け入れられた答えは正しいのですが、Mixinは有害であると考えられています( https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html )とReactチームによって考えられています。

もし誰かがこの質問に出くわして、これを行うための推奨される方法を探しているなら、私はMixinの代わりにHigher Order Componentsを使うことをお勧めします。

ここに、処理を進める前にユーザーがログインしているかどうかをチェックする HOC の例があります。そして、もしユーザーがログインしていない場合、ログインページにリダイレクトします。このコンポーネントは isLoggedIn と呼ばれるプロップを受け取ります。これは基本的に、ユーザーがログインしているかどうかを示すためにアプリケーションが保存できるフラグです。

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