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

问题描述 投票:0回答:1

当用户访问URL http://localhost:3000/dashboard时,我需要帮助,如果管理员已经登录,他将能够看到仪表板,我们只是在他的本地存储中验证令牌?我通过将它发送到node.js应用程序验证JSON Web令牌验证它是否好我们发送200状态,如果它的坏令牌我们发送401状态并根据状态我们设置私有路由显示真或假,获取功能已准备好但我无法找到一种方法来集成它

这是应用程序文件结构

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并根据响应我想显示仪表板或重定向到管理员登录表单

现在一切正常但只有当我手动更改isAuthenticated(在Auth类中)我找不到根据服务器的获取答案进行验证的方法时,我不确定是否应该使用该函数将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)
            })

    }

这是所有路线都在的App组件

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' />
    )} />
      )
}

这是:Auth类

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;

这是Admin Component的登录表单

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;
reactjs react-router
1个回答
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调用来获得true或false,将其设置为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' />
    )} />
      )
}
© www.soinside.com 2019 - 2024. All rights reserved.