reactjs
react-router

React-Router v4, firebaseの認証(リダイレクト)を解説


React-Router v4の認証の説明がクドい

Reactで認証が必要なプロジェクトに取り組む際は、ルーティングライブラリがとても大切になります。

現状Reactでルーティングを管理するのはReact-Routerがデファクトスタンダードです。

公式のリダイレクト説明がわかりづらかったので、自身の理解もかねて解説してみようと思います。

Firebaseを使う場合、ログインなどは非同期処理なので前述のfirebase.auth().currentUserなどはやめたほうがよさげ?


PrivateRoute.js

import React from 'react';

import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';

function PrivateRoute({ user, component: Component, ...rest }) {
return (
<Route
{...rest}
render={props =>

// ここで認証状態を取得します。
user!==null ? (
// ログイン済みならば、PrivateRouteに渡されたcomponentを返します。
<Component {...props} />
) : (
// ログインしてなければログインページ(/login)に飛ばします。
<Redirect
to='/login'
/>
)
}
/>
);
}

const mapStateToProps = state => ({
user: state.auth.user
})

export default connect(mapStateToProps)(PrivateRoute);


あとはRouteのほうで


Route.js

import PrivateRoute from './PrivateRoute';

//中略

// ログインしなくても見れるコンポーネント
<Route component={hogehoge} />
// ログイン後に見せたいコンポーネント
<PrivateRoute component={hogehoge} />


とすれば良いです。

ただこれだとリロードするたびログイン状態がふっとぶので、redux-persistなりlocalstorageに自前で保存するなりしましょう。(自戒)

-redux-persist, 導入簡単で効果バツグンなのでぜひ入れましょう。素晴らしいライブラリです。


結論


Route.js

const Routes = () => {

return (
<Router history={history}>
<div>
<Header />
<Switch>
<Route exact path='/' component={Home} />
<Route path='/login' component={LoginForm} />
<Route path='/welcome' component={WelcomeScreen} />
<PrivateRoute path='/map' component={UserMap} />
<Route path='/workermap' component={WorkerMap} />
<Route path='/choice' component={Choice} />
</Switch>
</div>
</Router>
)}

redux-persistを入れれば最初からストアにuserが入ります。PrivateRouteではストアの情報からログイン済か否かを判断して、ログインページor該当ページに飛ばすかを判断します。

こうすればRoute.jsは冗長なReduxなど入れずにきれいなままにできますね。参考まで。


追記 @ 2018/12/28

だめですね。これだとfirebase側でセッションの有効期限が切れていても、localstorageは永続的なので、ログイン済なのにfirebaseではログインされてないぞ?問題が発生します。

firebaseはfirebaseLocalStorageDbを保持していて、ログイン状態はここから取得できるようです。なので、インターネットを切断してもPrivateRouteに入れました。

image.png

reduxとか関係なく、単に下記のコードでセキュリティ上の問題はなさそうです。


PrivateRoute.js

import React from 'react';

import { Route, Redirect } from 'react-router-dom';
import firebase from 'firebase';

function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props =>
// ここで認証状態を取得します。
// firebaseだったらfirebase.auth.currentUser !== nullとかで同様になります。
firebase.auth.currentUser !== null ? (
// ログイン済みならば、PrivateRouteに渡されたcomponentを返します。
<Component {...props} />
) : (
// ログインしてなければログインページ(/login)に飛ばします。
<Redirect
to='/login'
/>
)
}
/>
);
}

// const mapStateToProps = state => ({
// user: state.auth.user
// })

export default PrivateRoute;


勉強になりました。そしてfirebaseはよく考えられている。