检查是否已登录 - React Router App ES6

Ser*_*kov 18 javascript authentication ecmascript-6 reactjs react-router

我正在使用react-router(v2.8.1)和ES6语法编写React .js应用程序(v15.3).我无法获取路由器代码来拦截页面之间的所有转换,以检查用户是否需要先登录.

我的顶级渲染方法非常简单(应用程序也很简单):

 render()
   {
      return (
         <Router history={hashHistory}>
            <Route path="/" component={AppMain}>
               <Route path="login" component={Login}/>
               <Route path="logout" component={Logout}/>
               <Route path="subject" component={SubjectPanel}/>
               <Route path="all" component={NotesPanel}/>
            </Route>
         </Router>
      );
   }
Run Code Online (Sandbox Code Playgroud)

Web上的所有示例都使用ES5代码或旧版本的react-router(早于版本2),而我对mixins(已弃用)和willTransitionTo(从未被调用)的各种尝试都失败了.

如何设置全局"拦截器功能"以强制用户在登陆他们请求的页面之前进行身份验证?

vij*_*yst 15

每个路由都有一个onEnter挂钩,在路由转换发生之前调用它.使用自定义的requireAuth函数处理onEnter挂钩.

<Route path="/search" component={Search} onEnter={requireAuth} />
Run Code Online (Sandbox Code Playgroud)

样本requireAuth如下所示.如果用户已通过身份验证,请通过next()进行转换.否则用/ login替换路径名并通过next()转换.登录也会传递当前路径名,以便在登录完成后,用户将被重定向到最初请求的路径.

function requireAuth(nextState, replace, next) {
  if (!authenticated) {
    replace({
      pathname: "/login",
      state: {nextPathname: nextState.location.pathname}
    });
  }
  next();
}
Run Code Online (Sandbox Code Playgroud)


eer*_*eam 6

在 v4 中,您只需创建一个路由组件来检查使用是否经过身份验证并返回下一个组件,当然下一个组件可以是其他路由。

import React, { Component } from 'react';
import PropTypes from 'prop-types';

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

import AuthMiddleware from 'modules/middlewares/AuthMiddleware';

class PrivateRoute extends Component {
  static propTypes = {
    component: PropTypes.func.isRequired,
    isAuthenticated: PropTypes.bool,
    isLoggedIn: PropTypes.func.isRequired,
    isError: PropTypes.bool.isRequired
  };

  static defaultProps = {
    isAuthenticated: false
  };

  constructor(props) {
    super(props);
    if (!props.isAuthenticated) {
      setTimeout(() => {
        props.isLoggedIn();
      }, 5);
    }
  }

  componentWillMount() {
    if (this.props.isAuthenticated) {
      console.log('authenticated');
    } else {
      console.log('not authenticated');
    }
  }
  componentWillUnmount() {}

  render() {
    const { isAuthenticated, component, isError, ...rest } = this.props;
    if (isAuthenticated !== null) {
      return (
        <Route
          {...rest}
          render={props => (
            isAuthenticated ? (
              React.createElement(component, props)
            ) : (
              <Redirect
                to={{
                  pathname: isError ? '/login' : '/welcome',
                  state: { from: props.location }
                }}
              />
            )
          )}
        />
      );
    } return null;
  }

}

const mapStateToProps = (state) => {
  return {
    isAuthenticated: state.auth.isAuthenticated,
    isError: state.auth.isError
  };
};

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
    isLoggedIn: () => AuthMiddleware.isLoggedIn()
  }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(PrivateRoute);
Run Code Online (Sandbox Code Playgroud)

  • 提供 AuthMiddleware 的模块名称是什么? (4认同)

Ser*_*kov 2

这个版本的 onEnter 回调终于适用于react-router(v2.8):

 requireAuth(nextState,
               replace)
   {
      if(!this.authenticated()) // pseudocode - SYNCHRONOUS function (cannot be async without extra callback parameter to this function)
         replace('/login')
   }
Run Code Online (Sandbox Code Playgroud)

解释 V1 与 v2 之间的 React-router 重定向差异的链接位于此处。相关部分引用如下:

Likewise, redirecting from an onEnter hook now also uses a location descriptor.

// v1.0.x
(nextState, replaceState) => replaceState(null, '/foo')
(nextState, replaceState) => replaceState(null, '/foo', { the: 'query' })

// v2.0.0
(nextState, replace) => replace('/foo')
(nextState, replace) => replace({ pathname: '/foo', query: { the: 'query' } })
Run Code Online (Sandbox Code Playgroud)

完整代码列表如下(react-router 版本 2.8.1):

requireAuth(nextState,
               replace)
{
   if(!this.authenticated()) // pseudocode - SYNCHRONOUS function (cannot be async without extra callback parameter to this function)
     replace('/login');
}

render() {
  return (
     <Router history={hashHistory}>
        <Route path="/" component={AppMain}>
           <Route path="login" component={Login}/>
           <Route path="logout" component={Logout}/>
           <Route path="subject" component={SubjectPanel} onEnter={this.requireAuth}/>
           <Route path="all" component={NotesPanel} onEnter={this.requireAuth}/>
        </Route>
     </Router>
  );
}
Run Code Online (Sandbox Code Playgroud)