2017-04-16 83 views
0

在react路由器中,我們如何構建基於認證的路由?在反應路由器中,我們如何建立基於認證的路由?

假設我們希望某些路由需要特定的身份驗證,比方說authTypeA,才能訪問,有些路由需要更多的身份驗證,比如說authTypeA,authTypeB,authTypeC。

那麼我們如何才能使這些在反應路由器(v2)?

回答

0
const Routes = (
<Route path="/" component={App}> 
    <Route component={requireAuth(['authenticated'], ['/trade'])}> 
    <Route path="/dualview" component={TradingViewContainer} /> 
    <Route path="/marketdata" component={MarketDataContainer} /> 
    </Route> 
    <Route path="/signin" component={SigninContainer} /> 
</Route> 
); 

我們可以使用HOC(高階組件)來建立基於驗證的路由,它在檢查驗證後管理對路徑的訪問。

在反應路由器v2中,您可以在具有驗證邏輯的高階組件中定義。

export default function(strategies = [], greenRoute = []) { 
    class Authentication extends Component { 
    constructor() { 
     super() 
     this.state = { allGreen: true } 
    } 
    componentWillMount() { // When access the route with first time 
     const { history, location } = this.props 
     if (greenRoute.indexOf(location.pathname) === -1) { 
     strategies.map((strategy) => { 
      if (!this.props.auth[strategy]) { 
      this.setState({ allGreen: false }) 
      history.replace(`signin?next=${location.pathname.slice(1)}`) 
      } 
     }) 
     } 
    } 
    componentWillUpdate(nextProps) { 
     const { history, auth } = this.props 
     if (greenRoute.indexOf(location.pathname) === -1) { 
     strategies.map((strategy) => { 
      if (!nextProps.auth[strategy]) { 
      this.setState({ allGreen: false }) 
      alert(I18n.t('auth.needSignin')) 
      history.replace(`signin?next=${location.pathname.slice(1)}`) 
      } 
     }) 
     } 
    } 
    shouldComponentUpdate(prevProps, prevState) { 
     const { location } = this.props 
     if (prevProps.location !== location) { 
     return true; 
     } 
     for (var i = 0; i < strategies.length; i++) { 
     return prevProps.auth[strategies[i]] !== this.props.auth[strategies[i]] 
     } 
    } 
    render() { 
     return this.state.allGreen ? this.props.children : (<div></div>) 
    } 
    } 

    function mapStateToProps(state) { 
    return { 
     auth: state.auth 
    } 
    } 

    return connect(mapStateToProps)(Authentication) 
} 

上面的代碼,你可以做一個邏輯,當this.state.allGreen是真的,那麼渲染this.props.children要訪問該組件。

在requireAuth組分(HOC),componentWillMount將打破在訪問其需要進行認證的特定成分,並檢查它是否具有認證狀態,然後再決定是否要被訪問或沒有。

而且,當認證狀態改變時,可以使用組件更新,以便訪問組件將被拒絕。

shouldComponentUpdate將用於表現。

此代碼建立在庫反應,反應路由器,redux上。

隨意使用!

0

在react-router中,可以給出一個在進入路由之前運行的函數。在那裏,你可以在出現問題的情況下進行驗證和重定向。檢查這個例子。希望它回答你

import React from 'react'; 
    import { IndexRoute, Route, Redirect } from 'react-router'; 
    import App from './App'; 
    import { getToken } from './main/services/cookie'; 
    import Navigation from './main/navigation/Navigation'; 
    import * as authenticationActions from './authentication/actions/authenticationActions'; 

    export default (store) => { 

     const performAuth = async (nextState, replace, callback) => { 
     const authenticated = store.getState().authentication.authenticated; 
     const token = getToken(); 

     if (!authenticated) { 
      await store.dispatch(authenticationActions.authenticate(token)); 
     } 
     callback(); 
     }; 

     const requireAuth = (nextState, replace) => { 
     const authenticated = store.getState().authentication.authenticated; 
     if (!authenticated) { 
      replace({ pathname: Navigation('login') }); 
     } 
     }; 

     const checkAuth = (nextState, replace) => { 
     const authenticated = store.getState().authentication.authenticated; 
     if (authenticated) { 
      replace({ pathname: Navigation('schedule') }); 
     } 
     }; 

    const languages = ['en', 'fr']; 

    return (
    <Route onEnter={performAuth}> 
     <Route path="/" component={App} > 
     <IndexRoute component={Login} onEnter={checkAuth} /> 
      <Route path={Navigation('login', language)} component={Login} onEnter={checkAuth} /> 
      <Route path={Navigation('schedule', language)} component={PersonalSchedule} onEnter={requireAuth} /> 
      <Route path={Navigation('profile', language)} component={Profile} onEnter={requireAuth} /> 
     </Route> 
     <Redirect from="*" to="/" /> 
    </Route> 
); 
};