【问题标题】:Server side React Router user authentication服务器端 React Router 用户认证
【发布时间】:2016-07-15 03:39:05
【问题描述】:

我在 Koa 服务器上运行 ReactRouter。

我的 Koa 服务器配置为所有请求都指向“index.html”(使用koa-connect-history-api-fallback),然后将请求转发到 ReactRouter。这一切都很好,除了我无法弄清楚如何进行用户身份验证。

我想保护我的路由,以便用户必须登录才能访问任何路由。问题是我的登录页面是路由之一,这意味着用户必须登录才能访问登录页面!

有没有解决这个问题的好方法?例如,在我的 Koa 服务器中,我可以以某种方式保护除“/login”路由之外的所有路由吗?我已经阅读了这个example,它负责 ReactRouter 中的身份验证,但对我来说,在客户端进行身份验证似乎很粗略。不过我可能不在基地。

如果你好奇,我正在工作react-redux-starter-kit

【问题讨论】:

    标签: reactjs redux react-router koa


    【解决方案1】:

    您可以使用装饰器验证您的顶级组件,例如

    // auth.js
    import React, {Component} from 'react';
    import { connect } from 'react-redux';
    
    export default function(ComposedComponent) {
        class Auth extends Component {
            static contextTypes = {
                router: React.PropTypes.object
            }
    
            componentWillMount() {
                if (!this.props.authenticated) {
                    this.context.router.push('/');
                }
            }
    
            componentWillUpdate(nextProps) {
                if (!nextProps.authenticated) {
                    this.context.router.push('/');
                }
            }
    
            render() {
                return <ComposedComponent {...this.props} />
            }
        }
    
        function mapStateToProps(state) {
            return {authenticated: state.auth.authenticated};
        }
    
        return connect(mapStateToProps)(Auth);
    }
    

    和:

    @auth
    ...your component...
    

    或者,如果你有一个 auth 模块,你可以用一种不那么“繁琐”的方式来做:

    function requireAuth(nextState, replace) {
      if (!auth.loggedIn()) {
        replace({
          pathname: '/login',
          state: { nextPathname: nextState.location.pathname }
        })
      }
    }
    
    render((
      <Router history={browserHistory}>
        <Route path="/" component={App}>
          <Route path="login" component={Login} />
          <Route path="logout" component={Logout} />
          <Route path="about" component={About} />
          <Route path="dashboard" component={Dashboard} onEnter={requireAuth} />
        </Route>
      </Router>
    ), document.getElementById('example'))
    

    【讨论】:

    • 使用 onEnter 进行客户端身份验证是否粗略?有人可以更改 javascript 来解决这个问题吗?
    • 您应该以可以绕过任何客户端障碍的想法进行编码 - 但只要对于每条安全数据(API 请求)您都发送一个正在服务器上验证的令牌然后没关系。所以即使他们到达了路由,提供敏感数据的请求仍然会失败。
    【解决方案2】:

    在这种情况下,我将放弃使用 ReactRouter 保护路由的责任,并在服务器上使用match 来确定当任何请求进入时您实际想要渲染/重定向到的路由。

    重要的是,当请求到达 Koa 服务器时,您会通过一些身份验证中间件运行它,该中间件能够告诉您用户是否经过身份验证以及他们的角色。然后,您希望这些信息反映在 Redux 存储中。您可以生成具有如下初始状态的商店:

    {
      user: {
        authenticated: true,
        role: 'admin'
      }
    }
    

    ,或者甚至更好的是,您可以在 reducer 为您执行此操作的商店上发送操作。

    现在,当您在服务器上创建路由(在您的存储中传递)时,React Router 将准确地知道什么可以,什么不可以。也就是说,如果您通过检查user.authenticated 使用onEnter 保护了路由,那么在服务器上调用match 将尊重这一点,并返回到/login 之类的重定向。 onEnter 的示例可能如下所示:

    const ensureLoggedIn = (nextState, replace) => {
        if (!store.getState().user.authenticated)) {
          replace('/login');
        }
    };
    

    您可以在redirectLocation 中捕获该重定向,这是对match 的回调中的一个参数。阅读有关匹配here 的所有信息。然后你就可以在新位置使用服务器res.redirect

    当然,这种类型的路由保护只是为了方便,您会希望合法地保护包含敏感信息的 API 端点。但这种方法非常宝贵,因为它使用相同的逻辑在客户端和服务器上进行路由,几乎不费吹灰之力。

    【讨论】:

      猜你喜欢
      • 2013-02-23
      • 2015-04-17
      • 1970-01-01
      • 1970-01-01
      • 2016-03-26
      • 1970-01-01
      • 1970-01-01
      • 2016-11-17
      • 1970-01-01
      相关资源
      最近更新 更多