如何在React Router中保护路由

时间:2020-11-11 14:25:18

标签: javascript node.js reactjs express passport.js

我正在使用带有Node&express的React和Express并使用本地护照和护照进行身份验证,我想知道如何保护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);
    }
};

4 个答案:

答案 0 :(得分:0)

在下面替换您的代码

except Exception as e:

请提供此代码

logging.exception(e)

答案 1 :(得分:0)

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

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;

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

答案 2 :(得分:0)

您的函数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,并确定是否是服务器端代码给您带来麻烦

...不要在顶部checkAuth的某个地方致电useEffect

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

答案 3 :(得分:0)

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

App.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。