ReactJS: Не удалось создать маршрут защиты для личного экрана

#javascript #reactjs #react-router #jwt

Вопрос:

На стороне клиента (Реагировать) У меня есть защищенный маршрут, доступ к которому возможен только при входе пользователя в систему.

В задней части (Node.js, Экспресс) Я использую JWT и сохраняю его в файлах cookie — токен доступа и токен обновления для аутентификации пользователя. Срок действия токена доступа истекает каждые 30 секунд, и токен обновления используется для повторного создания токена доступа.

Что я хочу сделать, так это создать защищенный маршрут для пользователя, вошедшего в систему, проверив, присутствуют ли файлы cookie accesToken и refreshtoken или нет, ниже приведен код:

Auth.js

 import axios from "axios";
import Cookies from "universal-cookie";
const cookies = new Cookies();

axios.defaults.withCredentials = true;
class Auth {
  constructor() {
    this.authenticated = false;
  }

  isAuthenticated() {
    const accessToken = cookies.get("authSession");
    const refreshToken = cookies.get("refreshTokenID");

    if (!accessToken amp;amp; !refreshToken) {
      return (this.authenticated = false);
    }

    if (accessToken amp;amp; refreshToken) {
      return (this.authenticated = true);
    }

    if (!accessToken amp;amp; refreshToken) {
      axios
        .post("/api/auth/refresh", {
          withCredentials: true,
        })
        .then(function (res) {
          console.log(res.data);
          // window.location.reload();
        })
        .catch(function (error) {
          console.log(error.response);
        });
    }
  }
}

export default new Auth();

 

ProtectedRoutes.js

 import { Route, Redirect } from "react-router-dom";
import Auth from "./Auth";

const ProtectedRoutes = ({ component: Component, ...rest }) => {
  console.log("🔐", Auth.isAuthenticated());

  return (
    <Route
      {...rest}
      render={(props) =>
        Auth.isAuthenticated() ? (
          <Component {...props} />
        ) : (
          <Redirect to="/loginRegister" />
        )
      }
    />
  );
};

export default ProtectedRoutes;

 

Все работает нормально, я могу войти в систему, срок действия файлов cookie истекает и они создаются заново каждые 30 секунд. За исключением случаев, когда срок действия маркера доступа истекает и создается заново, Auth.isAuthenticated() возвращается undefined . Он возвращается true только в течение первых 30 секунд (т. Е. Только до тех пор, пока не истечет срок действия первого файла cookie доступа), но когда я пытаюсь обновить свою личную страницу, он возвращается обратно на страницу регистрации входа
введите описание изображения здесь

файлы cookie также присутствуют: введите описание изображения здесь

Обновить

Я забыл добавить свой логин и маршрут приватного экрана:

Маршрут

 import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import LoginRegisterScreen from "../../screens/LoginRegisterScreen/LoginRegisterScreen";
import ProtectedRoutes from "../Protect/ProtectedRoutes";
import PrivateScreen from "../../screens/PrivateScreen/PrivateScreen";

const Body = () => {
  return (
    <Router>
      <Switch>
        <ProtectedRoutes exact path="/" component={PrivateScreen} />
        <Route exact path="/loginRegister" component={LoginRegisterScreen} />

      </Switch>
    </Router>
  );
};

export default Body;
 

Логин-манипулятор внутри моего loginRegisterScreen.js

 const loginHandler = async (e) => {
    e.preventDefault();
    console.log("Login hander called");

    const config = {
      headers: {
        "Content-Type": "application/json",
      },
    };

    try {
      await axios.post(
        "/api/auth/login",
        {
          email: loginEmail,
          password: loginPassword,
        },
        config
      );
      history.push("/");
    } catch (error) {
      setLoginError(error.response.data.error);
      setTimeout(() => {
        setLoginError("");
      }, 5000);
    }
  };
 

ОБНОВЛЕНИЕ 2

Оказывается, я все еще вошел в систему, если я ввожу свой личный URL вручную (т. Е. http://localhost:3000/ )в браузере, он позволяет мне получить к нему доступ, просто всякий раз, когда срок действия моего файла cookie истекает Auth.isAuthenticated() undefined , и меня возвращают на /loginRegister маршрут. Что я должен сделать, чтобы сделать это true вместо undefined этого .

ОБНОВЛЕНИЕ 3

Добавление изображений для лучшего понимания:

  1. Сразу после того, как я войду в систему, мой маршрут защиты вступит в действие, и откроется личный экран. введите описание изображения здесь
  2. Через 30 секунд, когда срок действия моего токена доступа истечет, если я обновлю страницу, я вернусь к /loginRegister маршруту, потому что некоторые его Auth.isAuthenticated() параметры не определены. введите описание изображения здесь
  3. Это происходит только тогда, когда я снова набираю URL вручную и ввожу, он переходит на частный маршрут: введите описание изображения здесь

ОБНОВЛЕНИЕ 4

Получение ошибки не определено введите описание изображения здесь

Ответ №1:

В Auth.js вы ничего не возвращаете после того, как потребовали новый доступ. Вы можете просто вернуть истину там, как показано ниже;

 ...
 if (!accessToken amp;amp; refreshToken) {
      axios
        .post("/api/auth/refresh", {
          withCredentials: true,
        })
        .then(function (res) {
          console.log(res.data);
          return (this.authenticated = true); // <-- this is a new piece of code here
          // window.location.reload();
        })
        .catch(function (error) {
          console.log(error.response);
        });
    }
 

Комментарии:

1. Спасибо за ответ, я пытался return (this.authenticated = true) , но я не знаю, почему он все еще отображается undefined , он возвращается только тогда, когда я набираю URL вручную return (this.authenticated = true) . Я обновил вопрос изображениями, чтобы лучше понять, что происходит.

2. Я думаю, вам нужно отладить isAuthenticated . Если он все еще не определен, он либо попадает в блок catch, либо не соответствует ни одному из условий if, isAuthentucated не определен, когда он ничего не возвращает

3. @AnkushDogra, вместо console.log(error.response); того, чтобы вы могли просто войти console.log(error); в блок caatch?

4. После регистрации я понял TypeError: this is undefined , что вы были правы, это зацепит блок,