React路由器v4 - 具有HOC的授权路由 [英] React router v4 - Authorized routes with HOC

查看:92
本文介绍了React路由器v4 - 具有HOC的授权路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,以防止未经授权的用户访问授权的路线/组件 - 如登录用户仪表板



我有以下代码:

  import从'react'反应
//其他进口
从'react-router'$导入{withRouter}

class用户扩展React.Component {
构造函数(道具){
super(道具)
console.log('道具',道具)
let user = JSON.parse(localStorage.getItem('userDetails'))
if(!user ||!user.user || props.match.params.steamId!== user.user.steamId){
props.history.push('/')
} else {
this.props.updateUserState(user)
this.props.getUser(user.user.steamId)
}
}

//渲染函数
}

// mapStateToProps和mapDispatchToProps

export default withRouter(connect (mapStateToProps,mapDispatchToProps)(User))

路由器:

  render(){
return(
< Router>
< div>
< Route path =/ user /:steamIdcomponent = {User} />
< / div>
< / Router>

}

我尝试记录以检查是否输入条件,它是,但是我从渲染函数得到一个错误,说它不能读取null的属性。



有没有办法解决我的问题,也是一个更好的方法来配合为我的要求?只有授权用户才能访问特定组件

解决方案

好的,根据您的逻辑,禁止未经授权的用户访问用户组件。简单而公平。没有问题。



但是我担心的是您是否在检查用户是否在未经身份验证的用户不应进入的组件内登录。这在我看来是不正确的,因为:


  1. 这是我们程序的额外旅程 - 增加了额外的不必要的低效率。有一种可能性,从路由器我们去用户组件,后者把我们送回到前者。 Ping pong。


  2. User组件看起来很脏。具有不相关的逻辑。是不相关的。由于验证检查不应在用户组件中完成。用户组件应该包含用户相关的东西。


你认为如果不是在用户组件内部检查用户身份验证,而是在路由器中检查它?正如其名称所描述的,用户组件专用于用户,检查身份验证的逻辑应从该处取出。



好的,这很酷。但是怎么做?



我们可以创建一个高阶组件(HOC)作为参数将采用任何组件传递给它。然后,我们在HOC中添加验证逻辑,最后,根据我们使用的逻辑,我们可以重定向到主页,或者允许请求到给定的组件。



为了让HOC能够完成上述操作,需要访问:


  1. 状态。我们需要知道用户是否已登录,并且状态是我们存储此类数据的地方。

  2. 路由器。我们可能需要重定向用户。

允许命名HOC required_auth 。这里是它的代码:

 从'react'导入React,{Component}; 
从'react-redux'导入{connect};

导出默认函数(ComposedComponent){
类认证扩展组件{
static contextTypes = {
router:React.PropTypes.object
}

componentWillMount(){
if(!this.props.authenticated){
this.context.router.history.push('/');



componentWillUpdate(nextProps){
if(!nextProps.authenticated){
this.context.router.history.push(' /');
}
}

render(){
return< ComposedComponent {... this.props} />



函数mapStateToProps(state){
return {authenticated:state.auth.authed};
}

return connect(mapStateToProps)(Authentication);

$ / code>

正如你所看到的,这里没有黑魔法发生。可能会引起混淆的是

$ $ $ $ $ $ c $ static静态类型= {
router:React.PropTypes.object
}




上下文是类似于道具,但它允许我们在组件层次结构中跳过
级别


因为 this.context 很容易被访问和滥用, React 迫使我们以这种方式定义上下文。



不要使用上下文除非你真的知道你在做什么。上下文的用例并不常见。阅读更多有关后果可能会如何此处



为了总结我们的HOC,它只需要一个组件作为参数,它可以重定向到主页或返回我们将传递给它的组件。



现在使用它,在路径文件中我们导入HOC

 从'./components/auth/required_auth'导入RequiredAuth; 

以及我们想要保护的任何路由与非授权用户保持一致,我们只需按如下方式进行路由:

 < Route path =/ usercomponent = {RequiredAuth(User)} /> 

上面的这行代码将直接到主页或者返回我们传递的组件,用户



参考文献:
https://facebook.github.io/react/docs/higher-order-components.html
https://facebook.github.io/react/docs/context.html


I have a problem to prevent unauthorized users from accessing authorized-only routes/components - such as logged in users dashboard

I have the following code:

import React from 'react'
//other imports
import {withRouter} from 'react-router'

class User extends React.Component {
  constructor(props) {
    super(props)
    console.log('props', props)
    let user = JSON.parse(localStorage.getItem('userDetails'))
    if(!user || !user.user || props.match.params.steamId !== user.user.steamId) {
      props.history.push('/')
    } else {
      this.props.updateUserState(user)
      this.props.getUser(user.user.steamId)
    }
  }

  //render function
}

//mapStateToProps and mapDispatchToProps

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(User))

The router:

render() {
    return (
      <Router>
        <div>
          <Route exact path="/" component={Main}/>
          <Route path="/user/:steamId" component={User}/>
          <Route path="/completelogin" component={CompleteLogin}/>
        </div>
      </Router>
    )
  }

I tried logging to check if the condition is entered and it is, however I get an error from the render function saying it cannot read properties of null.

Is there a way to fix my problem and also a better approach to cater for my requirement? where specific components will be strictly accessible only to authorized users

解决方案

Ok, so, according to your logic, unauthorized users are prohibited to access the User component. Simple and fair. No problems with that.

But my concern is that are you checking if the user is logged in inside a component which unauthenticated users should not get into. This is incorrect in my opinion because:

  1. It's an extra journey for our program - adds an extra bit of unnecessary inefficiency. There is a possibility that from the router we go to User component and the latter sends us back to the former. Ping pong.

  2. The User component looks dirty. Having irrelevant logic. Yes irrelevant. Because authentication check should not be done in User component. User component should contain user related stuff.

What do you think if instead of getting inside the User component to check users authentication, we check this in the router? User component, as it name describe, is dedicated for users and the logic to check authentication should be taken out from there.

Ok, Thats cool. But how?

We can create a Higher-Order Component (HOC) which as an argument will take any component was pass to it. Then, we add authentication logic inside the HOC and finally, depending on the logic we use we can either redirect to the homepage or allow the request to the given component.

In order for the HOC to be able to do the above it needs access to:

  1. State. We need to know whether the user is logged in and the state is where we store such data.
  2. Router. We may need to redirect users.

Lets name the HOC required_auth. Here is the code of it:

import React, { Component } from 'react';
import { connect } from 'react-redux';

export default function(ComposedComponent) {
    class Authentication extends Component {
        static contextTypes = {
            router: React.PropTypes.object
        }

        componentWillMount() {
            if (!this.props.authenticated) {
                this.context.router.history.push('/');
            }
        }

        componentWillUpdate(nextProps) {
            if (!nextProps.authenticated) {
                this.context.router.history.push('/');
            }
        }

        render() {
            return <ComposedComponent {...this.props} />
        }
    }

    function mapStateToProps(state) {
        return { authenticated: state.auth.authed };
    }

    return connect(mapStateToProps)(Authentication);
}

As you can see, there is no black magic happening here. What might be confusing is

static contextTypes = {
    router: React.PropTypes.object
}

context is similar to props but it allows us to skip levels in our component hierarchy

Because this.context is very easy to access and abuse, React forces us to define the context in this way.

Do not use context unless you really know what you are doing. The use case for context is not that common. Read more on what the consequences could be here

To conclude on our HOC, it simply takes a component as an argument and it either redirect to the homepage or returns the component that we will pass to it.

Now to use it, in route file we import the HOC

 import RequiredAuth from './components/auth/required_auth';

and any routes which we want to protect from non-authoirzed users we simply route it like this:

<Route path="/user" component={RequiredAuth(User)}/>

The line above will either direct to homepage or returns the component which we are passing, User

References: https://facebook.github.io/react/docs/higher-order-components.html https://facebook.github.io/react/docs/context.html

这篇关于React路由器v4 - 具有HOC的授权路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆