blog

React-Routerを使ったフロントエンドのルート認証

React-RouterはReactのエコシステムの非常に重要な部分であり、現在ルートのReactのシングルページのアプリケーションは、基本的に独自の管理のフロントエンドであり、以前のバックエンドルー...

Jun 26, 2020 · 8 min. read
シェア

React-RouterはReactエコシステムの非常に重要な部分であり、現在Reactのシングルページアプリケーションのルートは基本的に自社管理のフロントエンドであり、以前のバックエンドルーティングとは異なり、React管理ルーティングライブラリはReact-Routerが一般的に使用されています。いるので、一般的な開発シナリオでReact-Routerの使い方を確認します。一般的なシステムでは、ユーザのアクセス権限に制限があり、ページによっては特定の権限がないとアクセスできない場合があります。この記事ではReact-Routerを使ってフロントエンドの認証モデルを実装します。

アプリケーションの例

この記事では、機能を達成するために頻繁に遭遇するシナリオは、つまり、別のページにアクセスするために別のユーザーの役割を制御するには、4つのページの合計があります:

  1. /index: ホームページ
  2. /login:
  3. /backend: バックエンドページ
  4. /admin: 管理ページ

他にも3人の登場人物がいます:

  1. 非ログインユーザー:ホームページ/インデックスとログインページ/ログインへのアクセスのみ
  2. 一般ユーザー:トップページ/インデックス、ログインページ/ログイン、バックエンドページ/バックエンドにアクセスできます。
  3. 管理者:管理者ページ/管理者およびその他すべてのページへのアクセス権

React-Routerの紹介

まず、React-Routerを使って、これらのページを含む簡単なプロジェクトを作成します。create-react-appで直接新しいプロジェクトを作成し、前述のページを含むpagesフォルダを作成します:

ページの書き方はまずシンプルに、タイトルから始めましょう:

import React from 'react'; function Admin() { return ( <h1>管理者ページ</h1> ); }

他のいくつかのページも同様です。

React-Routerの新しいバージョンは、react-router-domを使用してブラウザで、React-Routerのコアロジック層と表示層に分離されることに注意してください、コアロジックは、ルートマッチングなどを処理し、表示層は、実際のジャンプとルート変更のリスニングを処理します、このような分離の理由は、React-Routerは、ブラウザをサポートするだけでなく、React Nativeをサポートする必要があります。React-Routerはブラウザをサポートするだけでなく、React Nativeもサポートする必要があり、これら2つのプラットフォームのリスニングとジャンプは異なるため、現在React-Router下にいくつかのパッケージがあります:

react-router: コアロジックの処理、いくつかの共通ベースクラスの提供

react-router-dom: ブラウザ関連のルートリスニングとジャンプを実装しています。

react-router-native: RN関連のルートリスニングとホッピングを実装します。

実際には、react-routerを参照する必要はなく、react-router-domを使用すればよいでしょう。

import React from 'react'; import { BrowserRouter as Router, Switch, Route, } from "react-router-dom"; import Home from './pages/Home'; import Login from './pages/Login'; import Backend from './pages/Backend'; import Admin from './pages/Admin'; function App() { return ( <Router> <Switch> <Route path="/login" component={Login}/> <Route path="/backend" component={Backend}/> <Route path="/admin" component={Admin}/> <Route path="/" component={Home}/> </Switch> </Router> ); } export default App;

そして、トップページの「リンク」を使って、他のページにジャンプするためのリンクを追加し、ジャンプできるようにします:

import React from 'react'; import { Link } from 'react-router-dom'; function Home() { return ( <> <h1> </h1> <ul> <li><Link to="/login"> </Link></li> <li><Link to="/backend"> </Link></li> <li><Link to="/admin"> </Link></li> </ul> </> ); } export default Home;

アプリケーションはこのように動作します:

モジュール分割

ジャンプは実現したものの、誰でもどのページにもアクセスできてしまうので、ログイン時の役割に応じてページへのアクセスを制限したいというのがこれまでの要望ですが、コードを書く前に、その方法を考えてみましょう。もちろん、最も直感的で簡単な方法は、各ページで現在のユーザーの役割を検出し、一致しない場合はエラーを報告するか、ホームページにジャンプバックすることです。今はページ数が少ないので、これでもよさそうですが、アプリケーションが大きくなれば、ページ数が多くなり、テストに各ページは非常に繰り返しになるので、別の視点からこの問題を考える必要があります。

よく見ると、実際には、3つの異なるアクセス許可に対応する3つの役割の合計は、これらの3つのアクセス許可と階層的な関係は、高レベルのアクセス許可は、低レベルのアクセス許可を含むので、ページは、これらのアクセス許可に応じてアクセス許可の3種類に分けることができます:

  1. 公開ページ:サイトのトップページやログインページなど、ログインしなくても誰でもアクセスできるページ。
  2. 一般ページ:一般のログインユーザーがアクセスできるページ
  3. 管理者ページ:管理者のみがアクセスできるページ

これら3つのタイプのページを管理するために、3つのファイルに抽出し、別のフォルダroutesに入れます。3つのファイルはpublicRoutes.js、privateRoutes.js、adminRoutes.jsと名付けました:

publicRoutes.jsのような外部呼び出しのために、ルートファイルごとに、そのようなルートを配列に整理し、エクスポートすることができます:

import Login from '../pages'; import Home from '../pages/Home'; const publicRoutes = [ { path: '/login', component: Login, exact: true, }, { path: '/', component: Home, exact: true, }, ]; export default publicRoutes;

そうすると、外部からの使用は直接読むことになります:

import publicRoutes from './routes/publicRoutes'; function App() { return ( <Router> <Switch> {publicRoutes.map( ({path, component, ...routes}) => <Route key={path} path={path} component={component} {...routes}/> )} <Route path="/backend" component={Backend}/> <Route path="/admin" component={Admin}/> </Switch> </Router> ); }

ルートの長いリストを持つ代わりに、App.jsは配列をループするだけです。しかし、アクセスするためにログインが必要なページや管理者ページでは、Routeコンポーネントを直接レンダリングすることができないため、高レベルのコンポーネントである認証作業をこのコンポーネントにカプセル化し、通常のページの実装が認証方法を気にする必要がないようにするのが最善です。

高度なコンポーネントのパッケージ化

この認証コンポーネントのアイデアをカプセル化することも非常に簡単です、Routeコンポーネントをレンダリングするサイクルに直接publicRoutesの前に、認証コンポーネントは、単に行にこれに基づいてロジックを追加する必要があります:現在のユーザーが対応するアクセス許可を持っているかどうかをチェックする前に、実際のRouteコンポーネントのレンダリングでは、Routeコンポーネントの直接レンダリングがある場合は、ない場合は、ページを返します。ページを返します。このページは、プロジェクトの要件に応じて、ログインページまたはホームページにすることができます。そのため、ルート内のルート設定ファイルprivateRoutes.js、adminRoutes.jsはpublicRoutes.js 2つ以上のパラメータになります:

// privateRoutes.js import Backend from '../pages/Backend'; const privateRoutes = [ { path: '/backend', component: Backend, exact: true, role: 'user', // 現在のルートに必要なロールパーミッション backUrl: '/login' // ジャンプ許可を満たさないルート }, ]; export default privateRoutes;

adminRoutes.jsも同様に書かれています:

// adminRoutes.js import Admin from '../pages/Admin'; const adminRoutes = [ { path: '/admin', component: Admin, exact: true, role: 'admin', // 必要なパーミッションはadmin backUrl: '/backend' // パーミッションを満たしていない場合は、バックグラウンドのページにジャンプして戻る }, ]; export default adminRoutes;

次に、高度なコンポーネントを書くことができ、その名前はAuthRoute、ユーザーのログインバックエンドAPIの仮定は、現在のユーザーの役割に返されることに注意してください、ユーザーは、一般ユーザーの役割は['user']であるような複数の役割を持っている可能性があり、管理者の役割は['user', 'admin']であり、特定のアクセス許可の検証ロジックは、独自のプロジェクトのアクセス許可に依存します!具体的なパーミッションのバリデーションロジックはプロジェクトのパーミッションの設計に依存します:

// AuthRoute.js import React from 'react'; import { Route, Redirect } from 'react-router-dom'; function AuthRoute(props) { const { user: { role: userRole }, role: routeRole, backUrl, ...otherProps } = props; // ユーザーにパーミッションがあれば、対応するルートをレンダリングする。 if (userRole && userRole.indexOf(routeRole) > -1) { return <Route {...otherProps} /> } else { // パーミッションがない場合、デフォルトルートが返される。 return <Redirect to={backUrl} /> } } export default AuthRoute;

次に、adminRoutes と privateRoutes のレンダリングに使用される AuthRoute を指定します。

// ... 他のコードを省略する... {privateRoutes.map( (route) => <AuthRoute key={route.path} {...route}/> )} {adminRoutes.map( (route) => <AuthRoute key={route.path} {...route}/> )}

ログインしてパーミッションを設定

AuthRouteでは、user: { role }という変数が使われていますが、まだ設定されていません。実際のプロジェクトでは、バックエンドAPIはログイン時に現在のユーザのロールを返し、フロントエンドはこのパーミッション情報をReduxなどの状態管理ツールに保存します。ここでは、このパーミッションをシミュレートするために、Loginページに2つのボタンを直接記述します。Loginページの2つのボタンは、対応する状態を変更します:

import React from 'react'; import { Link } from 'react-router-dom'; function Login(props) { const {loginAsUser, loginAsAdmin, history} = props; const userLoginHandler = () => { loginAsUser(); // 親メソッドを呼び出してユーザー権限を設定する history.replace('/backend'); // ログイン後のバックグラウンドページにジャンプする } const adminLoginHandler = () => { loginAsAdmin(); // 親メソッドを呼び出して管理者権限を設定する history.replace('/admin'); // ログイン後に管理者ページにジャンプする } return ( <> <h1> </h1> <button onClick={userLoginHandler}>一般ユーザーのログイン</button> <br/><br/> <button onClick={adminLoginHandler}>管理者ログイン</button> <br/><br/> <Link to="/"> </Link> </> ); } export default Login;

ここで、この簡単なルート認証が完了し、その効果までの具体的な流れは以下の通りです:

この記事のコード全体はGitHubにアップロードされているので、ダウンロードして遊んでみてください:github.com/dennis-jian...

まとめ

  1. React-Routerはフロントエンドのルーティングジャンプを管理するために使用でき、Reactエコシステム内の重要なライブラリです。
  2. React-Routerは、ブラウザとReact-Nativeの両方をサポートするために、react-routerコアパッケージ、react-router-domブラウザパッケージ、React-Nativeのためのreact-router-nativeサポートの3つのパッケージに分かれています。ルーターを導入する必要はなく、必要なプラットフォームパッケージを導入するだけです。
  3. 異なるパーミッションを必要とするルートについては、それらを実行し、別のファイルに分類するか、ルートが多くない場合は、複数のアレイをエクスポートするファイルにそれらを置くことができます。
  4. 認証が必要なルートに対して、アドバンストコンポーネントを使ってパーミッションチェックのロジックをカプセル化し、他のページは適切なコンフィギュレーションを追加するだけなので、認証の問題を気にする必要はまったくありません。

React-Routerの使用に精通しているとして、この記事の内容は単純ですが、悪いことではありませんが、使用するだけでなく、彼の原理を知ることができません。どのような謎がReact-Routerのソースコードの内側にあるかを見るために次の記事では、我々は、ハハを失っていない懸念を指すことができます!

公式ドキュメント:reactrouter.com/web/guides/...

GitHubソースアドレス:github.com/ReactTraini...

"フロントエンドの高度な知識 "の連載記事:

上級フロントエンド知識」シリーズのソースコードはGitHubで公開されています: github.com/dennis-jian...

Read next

アクティビティはどのように作成されるのか?

Activityを開始するメソッドを呼び出すとき、Activityのプロセスが存在するかどうかによって、システムは異なる処理を行う必要があります。 存在しない場合、AMSはソケット経由でZygoteにプロセスフォーク要求を開始し、フォークされた子プロセスから対応するAPPのActiviを実行する必要があります。...

Jun 26, 2020 · 9 min read