React js PrivateRoute show隐藏基于JSON Web令牌的仪表板组件并获取调用

时间:2019-03-27 16:42:12

标签: reactjs react-router

当用户转到URL http://localhost:3000/dashboard时,我需要帮助 如果管理员已经登录,那么他将只能看到他本地存储中的令牌吗?我通过将其发送到node.js应用程序来验证JSON Web令牌,以验证其是否良好,我们发送200状态,如果其错误的令牌,我们发送401状态,并根据状态将私有路由设置为显示true或false,提取功能已准备就绪,但我找不到集成它的方法

这是应用程序文件结构

my-app/
  README.md
  node_modules/
  package.json
  public/
    index.html
    favicon.ico
  src/
     |components/
      |Clien/
        |Home.js
        |Home.css
        |Header.js
        |Footer.js
      |admin/
        |Auth.js
        |PrivateRoute.js
        |Admin.js
        |Dashboard.js
        |Dashboard.css
      App.css
      App.js
      index.css
      index.js
      logo.svg

这是我用来检查本地存储中的JWT并验证将其发送到服务器的令牌以获取res并基于响应的功能,我想显示仪表板或重定向到Admin登录表单

现在一切正常,但仅当我手动更改(在Auth类中)isAuthenticated时,我才无法找到一种基于服务器获取答案的方式进行验证的方法, 我不确定是否应该将Auth类中的函数用作函数,还是应该创建一个带有state和componentDidMount()的Component

初学者,请引导我:

这是功能

componentDidMount(){
        //get token from local storage if there is one
        const jwttoken = localStorage.getItem('jwttoken');
        const bearer = 'Bearer '+ jwttoken;
           const data = new FormData();
           // get the website backend main url from .env
           const REACT_APP_URL = process.env.REACT_APP_URL
           fetch(`${REACT_APP_URL}/api/auth/verify`, {
                method: 'POST',
                headers: {
                    'Accept': 'application/json',
                    'Authorization': bearer,
                },
                body: data
           }).then( (res)=> {
               if (res.status === 401) {
                   res.json()
                   .then( (res)=> {
                       this.setState({
                        isLogedout: true,
                        })
                       localStorage.removeItem('jwttoken');
                   })
               } else if (res.status === 200) {
                   res.json()
                   .then((res)=> {
                    this.setState({
                         isLogedout: false,
                         adminEmail: res.adminEmail
                         })
                         this.props.history.push("/dashboard"); 

                   })
               }else{
                this.setState({
                    isLogedout: true,
                    })
                   localStorage.removeItem('jwttoken');
               }
           }).catch((err) => {
            // console.log(err)
            })

    }

这是所有路由都在其中的应用程序组件

import React, { Component } from "react";
import { Route, } from "react-router-dom";
// import Auth from "./Components/Admin/Auth"


import logo from "./Components/img/logo.jpg";
import headerimg from "./Components/img/header.png";
import "./App.css";
import Home from "./Components/Home";
import Dashboard from "./Components/Admin/Dashboard";
import Articles from "./Components/Articles";
import ArticleId from "./Components/ArticleId";
import Admin from "./Components/Admin/Admin.js";
import{ PrivateRoute} from "./Components/Admin/PrivateRoute.js";


class App extends Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
      webiste: {
        title: "Website title",
        headerimg: headerimg,
        altheaderimg: "website header image",
        logo: logo,
        logotitle: "website logo "
      },

    };
  }


  render() {
    return (
      <div className="app-container">
        <Route exact path='/' render={(props) => <Home {...props} setTab={"home"} />} />
        <Route exact path='/home' render={(props) => <Home {...props} setTab={"home"} />} />
        <Route path='/articles' render={(props) => <Articles {...props} setArticle={"false"} />} />
        <Route path='/article/:id' render={(props) => <ArticleId {...props.match.params} setArticle={"false"} />} />

        <Route exact path='/services' render={(props) => <Home {...props} setTab={"services"} />} />
        <Route exact path='/events' render={(props) => <Home {...props} setTab={"events"} />} />
        <Route exact path='/about' render={(props) => <Home {...props} setTab={"about"} />} />
        <Route exact path='/contact' render={(props) => <Home {...props} setTab={"contact"} />} />

        <Route exact path='/admin' component={Admin} />
        <PrivateRoute exact path="/dashboard" component={Dashboard}  />

      </div>

    );
  }
}

export default App;

这是: PrivateRoute组件

import React, { Component }  from  "react";
import { Route, Redirect, } from "react-router-dom";
import Auth from "./Auth"


export const PrivateRoute = ({ component: Component, ...rest }) => {
  return (
    <Route {...rest} render={(props) => (
      Auth.isAuthenticated() === true
        ? <Component {...props} />
        : <Redirect to='/admin' />
    )} />
      )
}

这是: 身份验证课程

class Auth {

    constructor() {
        this.authenticated = true;
    }

    login(cb) {
        this.authenticated = true;
        cb();
    }

    logout(cb) {
        this.authenticated = false;
        cb();
    }

    isAuthenticated() { 
        return this.authenticated;    

    }
}

export default new Auth();

这是: 仪表板组件对不起它的巨大作用,因此我不包括对我而言如何显示和隐藏在PrivateRouter中的所有重要内容

class Dashboard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      Articles: true,
      AddArticles: false,
      Messages: false,
      Services: false,
      Events: false,
      About: false,
      AdminContact: false,
      AdminAddEvent: false,
      WebsiteInfo: false,

      isLogedin: '',

      //dynamic className
      classArticles: "admin-side-bar-button-selected",
      classAddArticle: "admin-side-bar-button",
      classEvents: "admin-side-bar-button",
      classAddEvents: "admin-side-bar-button",
      classServices: "admin-side-bar-button",
      classAbout: "admin-side-bar-button",
      classContact: "admin-side-bar-button",
      classWebsiteInfo: "admin-side-bar-button",

    };
  }

  render() {
    return (
      <div>
      < div key="1" className="all-dashboard-container" >

        <div className="header-dashboard">
          <AdminHeader logout={this.logout} />
        </div>

        <div className="dashboard-container">
          <div className="side-dashboard">
            <button className={this.state.classArticles} onClick={this.showArticles}>Articles</button>
            <div className="hr"></div>
            <button className={this.state.classAddArticle} onClick={this.showAddArticles}>Add Aricle</button>
            <div className="hr"></div>
            <button className={this.state.classEvents} onClick={this.showEvents}>Events </button>
            <div className="hr"></div>
            <button className={this.state.classAddEvents} onClick={this.showAdminAddEvent}>Add Events</button>
            <div className="hr"></div>
            <button className={this.state.classServices} onClick={this.showServices}>Services </button>
            <div className="hr"></div>
            <button className={this.state.classAbout} onClick={this.showAbout}>About </button>
            <div className="hr"></div>
            <button className={this.state.classContact} onClick={this.showContact}>Contact</button>
            <div className="hr"></div>
            <button className={this.state.classWebsiteInfo} onClick={this.showWebsiteInfo}>Website Info </button>
            <div className="hr"></div>
          </div>

          <div className="body-dashboard">
            <div>
              <div>
                {this.state.Articles && <div> <AdminPublishedArticles /> </div>}
              </div>

              <div>
                {this.state.AddArticles && <div> <AdminAddArticle /> </div>}
              </div>

              <div>
                {this.state.AdminAddEvent && <div> <AdminAddEvent /> </div>}
              </div>

              <div>
                {this.state.Events && <div> <AdminPublishedEvents /> </div>}
              </div>

              <div>
                {this.state.Services && <div> <AdminServices /> </div>}
              </div>

              <div>
                {this.state.About && <div> <AdminAbout /> </div>}
              </div>

              <div>
                {this.state.AdminContact && <div> <AdminContact/> </div>}
              </div>

              <div>
                {this.state.WebsiteInfo && <div> <WebsiteInfo /> </div>}
              </div>

            </div>

          </div>
        </div>

        <div> <Footer/></div>

      </div>
      </div>
    );
  }
}

export default Dashboard;

这是管理组件及其登录表单

import React, { Component } from 'react';
import "./css/Admin.css";
import Auth from './Auth';
class Admin extends Component {
    constructor(props) {
        super(props);
        this.state = { 
            adminEmail: '',
            password: '',
            loginError: false,
            isLogedout: null

         }
    }

    componentDidMount(){
        //get token from local storage if there is one
        const jwttoken = localStorage.getItem('jwttoken');
        const bearer = 'Bearer '+ jwttoken;
           const data = new FormData();
           // get the website backend main url from .env
           const REACT_APP_URL = process.env.REACT_APP_URL
           fetch(`${REACT_APP_URL}/api/auth/verify`, {
                method: 'POST',
                headers: {
                    'Accept': 'application/json',
                    'Authorization': bearer,
                },
                body: data
           }).then( (res)=> {
               if (res.status === 401) {
                   res.json()
                   .then( (res)=> {
                       this.setState({
                        isLogedout: true,
                        adminEmail: res.adminEmail
                        })
                       localStorage.removeItem('jwttoken');
                   })
               } else if (res.status === 200) {
                   res.json()
                   .then((res)=> {
                    this.setState({
                         isLogedout: false,
                         adminEmail: res.adminEmail
                         })
                         this.props.history.push("/dashboard"); 

                   })
               }else{
                this.setState({
                    isLogedout: true,
                    adminEmail: res.adminEmail
                    })
                   localStorage.removeItem('jwttoken');
               }
           }).catch((err) => {
            // console.log(err)
            })

    }

    handleSubmit = (event) => {
        event.preventDefault();
           const data = new FormData();
           data.append('email', this.state.email);
           data.append('password', this.state.password);
           // get the website backend main url from .env
           const REACT_APP_URL = process.env.REACT_APP_URL
           fetch(`${REACT_APP_URL}/api/auth/login`, {
                method: 'POST',
                headers: {
                    'Accept': 'application/json',
                   //  'Content-Type': 'application/x-www-form-urlencoded'
                },
                body: data
           }).then( (response)=> {
               if (response.status === 401) {
                   response.json()
                   .then( (res)=> {
                       console.log(res)
                       this.setState({ loginError: true })
                   })
               } else if (response.status === 200) {
                   response.json()
                   .then((res) => {localStorage.setItem('jwttoken', res) })
                   .then((res)=> {
                       Auth.login(()=>{
                          this.props.history.push("/dashboard"); 
                       })

                   })
               }
           }).catch((err) => {
            err.json()
            .then(console.log(err))
            })
      }

    changeEventEmail = (event) => {
        this.setState({
            email: event.target.value,
            loginError: false
          });
    }

    changeEventPassword = (event) => {
        this.setState({
             password: event.target.value,
             loginError: false
             });
      }


    render() {
        return (
            <div>
             { this.state.isLogedout &&   
            <div className="admin-login-container">

                <form className="admin-login-form" onSubmit={this.handleSubmit}>
                    <label>Email</label>
                    <input type="text" onChange={this.changeEventEmail} value={this.state.email} required />
                    <label >Password </label>
                    <input type="text" onChange={this.changeEventPassword} value={this.state.password} required />
                    <input className="admin-login-submit" type="submit" value="Login" />
                </form>
                { this.state.loginError &&
                  <div className="admin-login-err">wrong email or password</div>
                }
            </div>  }
        </div>
         );
    }
}

export default Admin;

1 个答案:

答案 0 :(得分:0)

在Auth.js类中,将isAuthanticated更改为:

isAuthenticated() {
    //get token from local storage if there is one
    const jwttoken = localStorage.getItem('jwttoken');
    const bearer = 'Bearer ' + jwttoken;
    const data = new FormData();
    // get the website backend main url from .env
    const REACT_APP_URL = process.env.REACT_APP_URL
    fetch(`${REACT_APP_URL}/api/auth/verify`, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Authorization': bearer,
        },
        body: data
    }).then(
        (response) => {
            response.json()
                .then((res) => {
                    if (response.status === 200) {
                        this.authenticated = true;
                    }
                    if (response.status === 401) {
                        localStorage.removeItem('jwttoken');
                        this.authenticated = false;
                    }
                })
        }
    ).catch((err) => {
        console.log(err)
    });
    return this.authenticated;
}

在PrivateRoute中确保您调用Auth.isAuthanticated() 因此,根据fetch调用获得的是真还是假,女巫会将Authenticated设置为true或false,并将返回this.authenticated;。 您以正确的方式进行操作,只需检查拼写即可

import React, { Component }  from  "react";
import { Route, Redirect, } from "react-router-dom";
import Auth from "./Auth"


export const PrivateRoute = ({ component: Component, ...rest }) => {
  return (
    <Route {...rest} render={(props) => (
      Auth.isAuthenticated() === true
        ? <Component {...props} />
        : <Redirect to='/admin' />
    )} />
      )
}