React Router JWT защищает маршруты - PullRequest
0 голосов
/ 26 сентября 2019

У меня есть приложение реагирования поверх laravel, в котором у меня есть пользовательский экран входа в систему с использованием аутентификации jwt.Я получаю токен в локальном хранилище, но пытаюсь защитить и перенаправить маршруты, если не вошел в систему. Проблема в проверке токена перед обработкой маршрута.Все, что я пробовал, я в конечном итоге в огромной петле.Пожалуйста помоги.Вот мой app.jsx

require('./bootstrap');

import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'
import Login from './components/auth/login';
import Header from './components/header/';
import store from './store';
import Dashboard from './pages/dashboard';
import jwtDecode from 'jwt-decode';
import { PropsRoute, PublicRoute, PrivateRoute } from 'react-router-with-props';


let getToken = () =>{

  var auth = false;
  var token = localStorage.getItem('toobiauth')

  if(token){
    var tokenExpiration = jwtDecode(token).exp;
    var dateNow = new Date();

    if(tokenExpiration < dateNow.getTime()/1000){
        auth = false
    }else{
        auth = true
    }
  }else{
    auth = false
  }
  return auth;

}


ReactDOM.render((
  <Provider store={store}>
       <Router>
         <Header>
           <Switch> 
             <Route exact path='/' component={Login} />
             <Route exact path='/login' component={Login} />
             <PrivateRoute exact path="/dashboard" authed={getToken()} redirectTo="/login" component={Dashboard}/>
           </Switch>
           </Header>
       </Router>
    </Provider>
   ), document.getElementById('app'))

А вот мой логин

import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch, connect } from "react-redux";
import Submit from '../ui/buttons/submit';
import Textfield from '../ui/inputs/textfield';
import {loginUser} from '../../actions/authactions';
import jwtDecode from 'jwt-decode';


function login(props) {

    const auth = useSelector(state => state.auth)
    const [username, setUsername] = useState();
    const [password, setPassword] = useState();

    const submitLogin = () =>{
        props.dispatch(loginUser(username, password))
    }

    useEffect(() =>{
        var token = localStorage.getItem('toobiauth')

        if(token){
            var tokenExpiration = jwtDecode(token).exp;
            var dateNow = new Date();

            if(tokenExpiration < dateNow.getTime()/1000){
                console.log('expired');
            }else{
                props.history.push('/dashboard')
                console.log('login screen')
            }
        }

    },[auth]);


    return <div className="page_wrapper">
        <Textfield type="text" change={setUsername}/>
        <Textfield type="password" change={setPassword}/>
        <Submit action={submitLogin} width={'100%'}/>
    </div>;
}

const mapStateToProps = (state) =>{
    return {
      app: state.app,
    }
}

export default connect(mapStateToProps)(login);

1 Ответ

2 голосов
/ 26 сентября 2019

Вы можете определить свой собственный PrivateRoute.jsx, в этом компоненте вы можете проверить, прошел ли пользователь аутентификацию, а затем разрешить пользователю маршрутизировать защищенный маршрут, иначе перенаправить пользователя на маршрут входа

PrivateRoute.jsx

import React, { useEffect, useState} from 'react';
import { Route, Redirect } from 'react-router-dom'
import { useSelector } from "react-redux";

const PrivateRoute = ({ component: Component, ...rest }) => {
  const auth = useSelector(state => state.auth)
  const [isAuthenticated, setIsAuthenticated] = useState(null)  
  useEffect(() => {
    let token = localStorage.getItem('toobiauth')
        if(token){
            let tokenExpiration = jwtDecode(token).exp;
            let dateNow = new Date();

            if(tokenExpiration < dateNow.getTime()/1000){
                setIsAuthenticated(false)
            }else{
                setIsAuthenticated(true)
            }
        } else {
           setIsAuthenticated(false)
        }
    // eslint-disable-next-line
  }, [auth])

  if(isAuthenticated === null){
    return <></>
  }

  return (
    <Route {...rest} render={props =>
      !isAuthenticated ? (
        <Redirect to='/login'/>
      ) : (
        <Component {...props} />
      )
    }
    />
  );
};

export default PrivateRoute;

App.js

import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'
import Login from './components/auth/login';
import Header from './components/header/';
import store from './store';
import Dashboard from './pages/dashboard';
// import new PrivateRoute component defined in codeblock above
import PrivateRoute from './components/PrivateRoute'
import jwtDecode from 'jwt-decode';

ReactDOM.render((
  <Provider store={store}>
       <Router>
         <Header>
           <Switch> 
             <Route exact path='/' component={Login} />
             <Route exact path='/login' component={Login} />
             <PrivateRoute exact path='/dashboard' component={Dashboard} />
           </Switch>
           </Header>
       </Router>
    </Provider>
   ), document.getElementById('app'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...