NodeJS 如何在React路由器中保护路由

0tdrvxhp  于 2022-11-04  发布在  Node.js
关注(0)|答案(4)|浏览(155)

我的问题是什么?我的问题是什么?我的问题是什么?我的问题是什么?我的问题是什么?(
我正在使用带有Node & express的React,并使用passport和passport local进行身份验证,我想知道如何在React中保护路由,我的意思是,我想仅在用户通过身份验证时显示组件,否则我想在登录页面上重定向组件。
在我的情况下,我想保护Notes路线,我正在尝试的方法是不工作的所有...

我的React代码

import React from 'react';
import { Switch, Route, Redirect } from 'react-router-dom';
import axios from 'axios';

import Register from './Components/Register';
import Login from './Components/Login';
import Notes from './Components/Notes';

function App () {

  //Function to check authentication from server
  const checkAuth = () => {
    axios.get('http://localhost:8000/notes', { withCredentials : true })
    .then(res => res.data)
  }

  return (
    <Switch>
      <Route exact path='/' component={Register} />
      <Route exact path='/login' component={Login} />

      <Route exact path='/notes' render={() => {
         return checkAuth()? (
             <Notes />
           ) : (
             <Redirect to="/login" />
           )
      }} />
    </Switch>
  );
};

export default App;

和我的服务器端代码

//Notes Page
router.get('/notes', (req, res) => {
    if(req.isAuthenticated()) {
        res.send(req.user.email);
    }else{
        res.send(false);
    }
};
1hdlvixo

1hdlvixo1#

考虑显示加载器,直到api调用返回值。api调用返回值后,使用更高顺序的组件呈现所需的组件。

应用程序.jsx

class App extends Component {

state = {
    login: false,
    loading: false,
}

componentDidMount() {
    //Function to check authentication from server
    this.setState( {loadnig:true}, () => {
    this.checkAuth()
    }
}

checkAuth = () => {
    // API request to check if user is Authenticated
    axios.get('http://localhost:8000/notes', { withCredentials : true })
    .then( res => {
        console.log(res.data);
        // API response with data => login success!
        this.setState({
            login: true,
            loading:false
        });
    });
    .catch( error => {
        console.error(error);
        // Handle error
        this.setState({
            loading:false
        });
    });
}

render() {
    let {login, loading} = this.state
    let protectedRoutes = null;

    if(loading){
      return <loader/>
    }

    return (
        <Switch>
            //use authorize HOC with three parameters: component, requiresLogin, isLoggedIn
            <Route exact path='/path' component={authorize(component, true, login)} />
            <Route exact path='/' component={Register} />
            <Route exact path='/login' component={Login} />
        </Switch>
    );
}
};

export default App;

使用高阶组件将使您能够根据用户的登录状态灵活地控制路由。

授权,jsx

export default function (componentToRender, requiresLogin, isLoggedIn) {

  class Authenticate extends React.Component<> {
  render() {
      if (requiresLogin) {
          //must be logged in to view the page
          if (!isLoggedIn) {
              // redirect to an unauthorised page or homepage
              this.props.history.push('/unauthorised');
              return;
              // or just return <unauthoriesd {...this.props} />;
          }
      } else {
          // to be shown to non loggedin users only. Like the login or signup page
          if (isLoggedIn) {
              this.props.history.push('/unauthorised');
              return;
              //or just return <home {...this.props} />;
          }
      }
      //if all the conditions are satisfied then render the intended component.
      return <componentToRender {...this.props} />;
  }

  }
  return Authenticate;
}

此外,如果您决定为路由添加更多条件,那么您可以轻松地将这些条件添加到HOC。

yduiuuwa

yduiuuwa2#

通过“服务器请求”检查登录状态需要时间!然后考虑创建一个带有state的类!下面我给你一个例子:

import React, { Component } from 'react';
import { Switch, Route, Redirect } from 'react-router-dom';
import axios from 'axios';

import Register from './Components/Register';
import Login from './Components/Login';
import Notes from './Components/Notes';

class App extends Component {

    state = {
        login: false
    }

    componentDidMount() {
        //Function to check authentication from server
        this.checkAuth()
    }

    checkAuth = () => {
        // API request to check if user is Authenticated
        axios.get('http://localhost:8000/notes', { withCredentials : true })
        .then( res => {
            console.log(res.data);
            // API response with data => login success!
            this.setState({
                login: true
            });
        });
    }

    render() {

        let protectedRoutes = null;
        if(this.state.login === true) {
            // if login state is true then make available this Route!
            protectedRoutes = <Route exact path='/notes' component={Notes} />
        }

        return (
            <Switch>
                <Route exact path='/' component={Register} />
                <Route exact path='/login' component={Login} />
                { protectedRoutes }
            </Switch>
        );
    }
};

export default App;

我希望这个例子对你有用。

mec1mxoz

mec1mxoz3#

您的函数checkAuth由于进行网络调用可能无法及时返回正确的值以进行渲染,您应该做的是创建一个状态以确定用户是否经过身份验证,并让checkAuth更新该状态。

const [authenticated, updateAuthenticated] = useState(false);

...请更新checkAuth以更新已验证状态

//Function to check authentication from server
const checkAuth = () => {
    axios.get('http://localhost:8000/notes', { withCredentials : true })
    .then(res => updateAuthenticated(res.data)); // double check to ensure res.data contains the actual value returned
  }

...更新渲染以使用状态

<Route exact path='/notes' render={() => {
     return (authenticated ? 
         (<Notes />)
        : 
         (<Redirect to="/login" />)
       )
  }} />

......使用这种方法,您还可以将useState中的默认值设置为true或false,并确定是否是服务器端代码造成了问题
...不要在useEffect的顶部某处调用checkAuth

useEffect(()=>{
    checkAuth()
},[])
toiithl6

toiithl64#

替换下面的代码

<Route exact path='/notes' render={() => {
         checkAuth()? (
             <Notes />
           ) : (
             <Redirect to="/login" />
           )
      }} />

请使用此代码

<Route exact path="/notes">{checkAuth ? <Notes /> : <Redirect to="/login" />}</Route>

相关问题