Javascript 如何在登录reactjs后创建受保护的路由

Javascript 如何在登录reactjs后创建受保护的路由,javascript,reactjs,Javascript,Reactjs,我是个新手。我正在尝试创建一个项目,在这个项目中,用户必须登录才能访问页面,并且我希望保护一条只有在成功登录后才能访问的路由。我不想要花哨的用户管理或类似的东西,所以请不要推荐上下文或redux。我只希望我的localhost:3000/editor只有在登录后才能访问,如果有人试图在不登录的情况下访问/editor,那么他们将被重定向到登录页面。所以像IsAuthenticated:true/false这样的东西在我的情况下是可以的,我相信,但我不确定如何在我的webapp中传递它。如果有人能

我是个新手。我正在尝试创建一个项目,在这个项目中,用户必须登录才能访问页面,并且我希望保护一条只有在成功登录后才能访问的路由。我不想要花哨的用户管理或类似的东西,所以请不要推荐上下文或redux。我只希望我的localhost:3000/editor只有在登录后才能访问,如果有人试图在不登录的情况下访问/editor,那么他们将被重定向到登录页面。所以像IsAuthenticated:true/false这样的东西在我的情况下是可以的,我相信,但我不确定如何在我的webapp中传递它。如果有人能教我怎么做,我会很高兴的? 我创建了这个,但是有很多错误

App.js

import React, {useState} from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import "./App.css";
import Login from "./login";
import Dashboard from "./dashboard";
function App() {
 const [loggedIN, setLoggedIN]=useState(false);
  let privateRoutes = null;
   if(loggedIN){
      privateRoutes =(
        <Route path="/dashboard" component={Dashboard} />
      )}  
  return (
  <>  

  <Router>
      <div className="container">
        <nav className="navbar navbar-expand-lg navheader">
          <div className="collapse navbar-collapse">
            <ul className="navbar-nav mr-auto">
              <li className="nav-item">
                <Link to={"/Login"} className="nav-link">
                  Login
                </Link>
              </li>
            </ul>
          </div>
        </nav>
        <br />
        <Switch>
          <Route exact path="/login" component={Login} />
          {privateRoutes}
        </Switch>
      </div>
    </Router>
  </>);
}
export default App;

import React,{useState}来自“React”;
从“react Router dom”导入{BrowserRouter as Router,Switch,Route,Link};
导入“/App.css”;
从“/Login”导入登录名;
从“/Dashboard”导入仪表板;
函数App(){
const[loggedIN,setLoggedIN]=useState(false);
让privateRoutes=null;
if(loggedIN){
私家路=(
)}  
返回(
  • 登录

{privateRoutes} ); } 导出默认应用程序;
login.js

import React, { Component } from "react";
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";
import AppBar from "material-ui/AppBar";
import RaisedButton from "material-ui/RaisedButton";
import TextField from "material-ui/TextField";
import { Link } from "react-router-dom";
import "./loginForm.css";
class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: ""
    };
    this.onchange = this.onchange.bind(this);
  }
  onchange(e) {
    this.setState({ [e.target.name]: e.target.value });
  }
  performLogin = async () => {
    var body = {
      password: this.state.password,
      email: this.state.email
    };
    const options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      body: JSON.stringify(body)
    };
    const url = "/api/authenticate";
    try {
      const response = await fetch(url, options);
      const text = await response.text();
      if (text === "redirect") {
        this.props.setState({loggedIN: true})
        this.props.history.push(`/dashboard`);
      } else {
        console.log("login failed");
        window.alert("login failed");
      }
    } catch (error) {
      console.error(error);
    }
  };

  render() {
    return (
      <>
        <div className="loginForm">
          <MuiThemeProvider>
            <TextField
              hintText="Enter your Email"
              floatingLabelText="Email"

              onChange={(event, newValue) => this.setState({ email: newValue })}
            />

            <br />
            <TextField
              type="password"
              hintText="Enter your password"
              floatingLabelText="password"

              onChange={(event, newValue) =>
                this.setState({ password: newValue })
              }
            />

            <br />
            <RaisedButton
              label="Submit"
              primary={true}
              style={style}
              onClick={event => this.performLogin(event)}
            />

          </MuiThemeProvider>
        </div>
      </>
    );
  }
}
const style = {
  margin: 15
};
export default Login;
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";
import AppBar from "material-ui/AppBar";
import RaisedButton from "material-ui/RaisedButton";
import TextField from "material-ui/TextField";
import { Link } from "react-router-dom";
import "./loginForm.css";
import Cookies from 'universal-cookie';
const cookies = new Cookies();

class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: ""
    };
    this.onchange = this.onchange.bind(this);
  }
  onchange(e) {
    this.setState({ [e.target.name]: e.target.value });
  }
  performLogin = async () => {
    var body = {
      password: this.state.password,
      email: this.state.email
    };
    const options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      body: JSON.stringify(body)
    };
    const url = "/api/authenticate";
    try {
      const response = await fetch(url, options);
      const text = await response.text();
      // here you will get auth token in response
      // set token in cookie like cookie.set('token', response.token);
      cookies.set('loggedin', true);

      if (text === "redirect") {
        this.props.setState({loggedIN: true})
        this.props.history.push(`/dashboard`);
      } else {
        console.log("login failed");
        window.alert("login failed");
      }
    } catch (error) {
      console.error(error);
    }
  };

  render() {
    return (
      <>
        <div className="loginForm">
          <MuiThemeProvider>
            <TextField
              hintText="Enter your Email"
              floatingLabelText="Email"

              onChange={(event, newValue) => this.setState({ email: newValue })}
            />

            <br />
            <TextField
              type="password"
              hintText="Enter your password"
              floatingLabelText="password"

              onChange={(event, newValue) =>
                this.setState({ password: newValue })
              }
            />

            <br />
            <RaisedButton
              label="Submit"
              primary={true}
              style={style}
              onClick={event => this.performLogin(event)}
            />

          </MuiThemeProvider>
        </div>
      </>
    );
  }
}
const style = {
  margin: 15
};
export default Login; 
import React,{Component}来自“React”;
从“材质ui/styles/MuiThemeProvider”导入MuiThemeProvider;
从“物料界面/AppBar”导入AppBar;
从“物料界面/RaisedButton”导入RaisedButton;
从“物料界面/文本字段”导入文本字段;
从“react router dom”导入{Link};
导入“/loginForm.css”;
类登录扩展组件{
建造师(道具){
超级(道具);
此.state={
电邮:“,
密码:“
};
this.onchange=this.onchange.bind(this);
}
onchange(e){
this.setState({[e.target.name]:e.target.value});
}
performLogin=async()=>{
变量体={
密码:this.state.password,
电子邮件:this.state.email
};
常量选项={
方法:“张贴”,
标题:{
“内容类型”:“应用程序/json”,
接受:“应用程序/json”
},
body:JSON.stringify(body)
};
const url=“/api/authenticate”;
试一试{
const response=等待获取(url、选项);
const text=等待响应。text();
如果(文本==“重定向”){
this.props.setState({loggedIN:true})
this.props.history.push(`/dashboard`);
}否则{
console.log(“登录失败”);
window.alert(“登录失败”);
}
}捕获(错误){
控制台错误(error);
}
};
render(){
返回(
this.setState({email:newValue})}
/>

this.setState({password:newValue}) } />
this.performLogin(事件)} /> ); } } 常量样式={ 差额:15 }; 导出默认登录;
编辑页

import React, { Component } from "react";

class Dashboard extends Component {
constructor(props) {
    super(props);

  }
logout=()=>{
  this.setState({loggedIN: false)}
}  
render() {
    return (
         <div>hello</div>;
        <button onCLick={logout}>Logout</button>  
        )
   }
}
export default Dashboard;
import React,{Component}来自“React”;
类仪表板扩展组件{
建造师(道具){
超级(道具);
}
注销=()=>{
this.setState({loggedIN:false)}
}  
render(){
返回(
你好
注销
)
}
}
导出默认仪表板;

编辑:

成功登录后,您可能会获得用于授权目的的令牌。 因此,成功登录后,您可以将身份验证令牌存储在cookie中

install - npm i universal-cookie --save
login.js

import React, { Component } from "react";
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";
import AppBar from "material-ui/AppBar";
import RaisedButton from "material-ui/RaisedButton";
import TextField from "material-ui/TextField";
import { Link } from "react-router-dom";
import "./loginForm.css";
class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: ""
    };
    this.onchange = this.onchange.bind(this);
  }
  onchange(e) {
    this.setState({ [e.target.name]: e.target.value });
  }
  performLogin = async () => {
    var body = {
      password: this.state.password,
      email: this.state.email
    };
    const options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      body: JSON.stringify(body)
    };
    const url = "/api/authenticate";
    try {
      const response = await fetch(url, options);
      const text = await response.text();
      if (text === "redirect") {
        this.props.setState({loggedIN: true})
        this.props.history.push(`/dashboard`);
      } else {
        console.log("login failed");
        window.alert("login failed");
      }
    } catch (error) {
      console.error(error);
    }
  };

  render() {
    return (
      <>
        <div className="loginForm">
          <MuiThemeProvider>
            <TextField
              hintText="Enter your Email"
              floatingLabelText="Email"

              onChange={(event, newValue) => this.setState({ email: newValue })}
            />

            <br />
            <TextField
              type="password"
              hintText="Enter your password"
              floatingLabelText="password"

              onChange={(event, newValue) =>
                this.setState({ password: newValue })
              }
            />

            <br />
            <RaisedButton
              label="Submit"
              primary={true}
              style={style}
              onClick={event => this.performLogin(event)}
            />

          </MuiThemeProvider>
        </div>
      </>
    );
  }
}
const style = {
  margin: 15
};
export default Login;
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";
import AppBar from "material-ui/AppBar";
import RaisedButton from "material-ui/RaisedButton";
import TextField from "material-ui/TextField";
import { Link } from "react-router-dom";
import "./loginForm.css";
import Cookies from 'universal-cookie';
const cookies = new Cookies();

class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: ""
    };
    this.onchange = this.onchange.bind(this);
  }
  onchange(e) {
    this.setState({ [e.target.name]: e.target.value });
  }
  performLogin = async () => {
    var body = {
      password: this.state.password,
      email: this.state.email
    };
    const options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      body: JSON.stringify(body)
    };
    const url = "/api/authenticate";
    try {
      const response = await fetch(url, options);
      const text = await response.text();
      // here you will get auth token in response
      // set token in cookie like cookie.set('token', response.token);
      cookies.set('loggedin', true);

      if (text === "redirect") {
        this.props.setState({loggedIN: true})
        this.props.history.push(`/dashboard`);
      } else {
        console.log("login failed");
        window.alert("login failed");
      }
    } catch (error) {
      console.error(error);
    }
  };

  render() {
    return (
      <>
        <div className="loginForm">
          <MuiThemeProvider>
            <TextField
              hintText="Enter your Email"
              floatingLabelText="Email"

              onChange={(event, newValue) => this.setState({ email: newValue })}
            />

            <br />
            <TextField
              type="password"
              hintText="Enter your password"
              floatingLabelText="password"

              onChange={(event, newValue) =>
                this.setState({ password: newValue })
              }
            />

            <br />
            <RaisedButton
              label="Submit"
              primary={true}
              style={style}
              onClick={event => this.performLogin(event)}
            />

          </MuiThemeProvider>
        </div>
      </>
    );
  }
}
const style = {
  margin: 15
};
export default Login; 
从“材质ui/样式/MuiThemeProvider”导入MuiThemeProvider;
从“物料界面/AppBar”导入AppBar;
从“物料界面/RaisedButton”导入RaisedButton;
从“物料界面/文本字段”导入文本字段;
从“react router dom”导入{Link};
导入“/loginForm.css”;
从“通用cookie”导入cookie;
const cookies=新cookies();
类登录扩展组件{
建造师(道具){
超级(道具);
此.state={
电邮:“,
密码:“
};
this.onchange=this.onchange.bind(this);
}
onchange(e){
this.setState({[e.target.name]:e.target.value});
}
performLogin=async()=>{
变量体={
密码:this.state.password,
电子邮件:this.state.email
};
常量选项={
方法:“张贴”,
标题:{
“内容类型”:“应用程序/json”,
接受:“应用程序/json”
},
body:JSON.stringify(body)
};
const url=“/api/authenticate”;
试一试{
const response=等待获取(url、选项);
const text=等待响应。text();
//在这里,您将得到auth令牌作为响应
//像cookie.set('token',response.token)一样在cookie中设置令牌;
cookies.set('loggedin',true);
如果(文本==“重定向”){
this.props.setState({loggedIN:true})
this.props.history.push(`/dashboard`);
}否则{
console.log(“登录失败”);
window.alert(“登录失败”);
}
}捕获(错误){
控制台错误(error);
}
};
render(){
返回(
this.setState({email:newValue})}
/>

this.setState({password:newValue}) } />
this.performLogin(事件)} /> ); } } 常量样式={ 差额:15 }; 导出默认登录;
之后,在仪表板组件中检查cookie中的loggedin布尔值(如果存在),然后检查其登录和验证。例如

dashboard.js

import React, { Component } from "react";
import {Redirect} from 'react-router-dom'
import Cookies from 'universal-cookie';
const cookies = new Cookies();


class Dashboard extends Component {
constructor(props) {
    super(props);

  }
logout=()=>{
  this.setState({loggedIN: false)}
  cookies.set('loggedin', false);
}  
render() {
    // notice here
    if (!cookies.get('loggedin')) {
            return (<Redirect to={'/login'}/>)
        }

    return (
         <div>hello</div>;
        <button onCLick={logout}>Logout</button>  
        )
   }
}
export default Dashboard;
import React,{Component}来自“React”;
从“react router dom”导入{Redirect}
从“通用cookie”导入cookie;
const cookies=新cookies();
类仪表板扩展组件{
常数
<Route path="/home" render={() => {
      if(loggedIN){
      return(<Dashboard ...props/>)
     }else{
             return(<Login ...props/>)
          }
 }} />
import React, { Component } from "react";

class Dashboard extends Component {
constructor(props) {
    super(props);

  }
// logout function should not be here it should write in app.js and pass to
// this component with props and just call here if needed
 // and you should use this.logout = () ...
logout=()=>{
  //                      and here
  this.setState({loggedIN: false**)**}
}  
render() {
// here!!! jsx element should wrapped with an element
    return (
        // <div>
         <div>hello</div>;
        <button onCLick={logout}>Logout</button>  
      //</div>
        )
   }
}
export default Dashboard;
import { createDevTools } from 'redux-devtools'
import LogMonitor from 'redux-devtools-log-monitor'
import DockMonitor from 'redux-devtools-dock-monitor'

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, combineReducers, applyMiddleware, compose } from 'redux'
import { Provider } from 'react-redux'
import thunkMiddleware from 'redux-thunk'

import * as reducers from './reducers'
import App from './components/App'

const reducer = combineReducers(Object.assign({}, reducers, {}))

const DevTools = createDevTools(
  <DockMonitor toggleVisibilityKey="ctrl-h"
               changePositionKey="ctrl-q">
    <LogMonitor theme="tomorrow" />
  </DockMonitor>
)

const enhancer = compose(
  // Middleware you want to use in development:
  applyMiddleware(thunkMiddleware),
  DevTools.instrument()
)

// Note: passing enhancer as the last argument requires redux@>=3.1.0
const store = createStore(reducer, enhancer)

ReactDOM.render(
  <Provider store={store}>
    <div>
      <App />
      {/* <DevTools /> */}
    </div>
  </Provider>,
  document.getElementById('mount')
)
import locationHelperBuilder from 'redux-auth-wrapper/history4/locationHelper'
import { connectedRouterRedirect } from 'redux-auth-wrapper/history4/redirect'
import connectedAuthWrapper from 'redux-auth-wrapper/connectedAuthWrapper'

import Loading from './components/Loading'

const locationHelper = locationHelperBuilder({})

const userIsAuthenticatedDefaults = {
  authenticatedSelector: state => state.user.data !== null,
  authenticatingSelector: state => state.user.isLoading,
  wrapperDisplayName: 'UserIsAuthenticated'
}

export const userIsAuthenticated = connectedAuthWrapper(userIsAuthenticatedDefaults)

export const userIsAuthenticatedRedir = connectedRouterRedirect({
  ...userIsAuthenticatedDefaults,
  AuthenticatingComponent: Loading,
  redirectPath: '/login'
})

export const userIsAdminRedir = connectedRouterRedirect({
  redirectPath: '/',
  allowRedirectBack: false,
  authenticatedSelector: state => state.user.data !== null && state.user.data.isAdmin,
  predicate: user => user.isAdmin,
  wrapperDisplayName: 'UserIsAdmin'
})

const userIsNotAuthenticatedDefaults = {
  // Want to redirect the user when they are done loading and authenticated
  authenticatedSelector: state => state.user.data === null && state.user.isLoading === false,
  wrapperDisplayName: 'UserIsNotAuthenticated'
}

export const userIsNotAuthenticated = connectedAuthWrapper(userIsNotAuthenticatedDefaults)

export const userIsNotAuthenticatedRedir = connectedRouterRedirect({
  ...userIsNotAuthenticatedDefaults,
  redirectPath: (state, ownProps) => locationHelper.getRedirectQueryParam(ownProps) || '/protected',
  allowRedirectBack: false
})
import { userIsAuthenticated, userIsNotAuthenticated } from './auth';
// ...code
const isNotAuth = userIsNotAuthenticated(Login);
const isAuth = userIsAuthenticated(AuthRoutes);
// ...code
<Switch>
  <Route exact path="/login" component={isNotAuth} /> // Notice the *exact* path
  <Route path="/" component={isAuth} /> // Notice the *not exact path*
  <Route path="" component={NotFoundPage} />
</Switch>
// ...code

<Switch>
  <Route exact path="/homepage" component={HomePage} />
  // ...other routes
</Switch>