ReactJS:无法为私人屏幕创建保护路由

IT技术 javascript reactjs react-router jwt
2021-05-19 12:18:21

客户端(React),我有一个受保护的路由,只能在用户登录时访问。

后端(Node.js、Express)中,我使用 JWT 并将其存储在 cookie 中 - 访问令牌和刷新令牌以对用户进行身份验证。访问令牌每 30 秒过期一次,刷新令牌用于重新创建访问令牌。

我想要做的是为登录用户创建一个受保护的路由,通过检查 accesToken cookie 和 refreshtoken cookie 是否存在,以下是代码:

身份验证.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 && !refreshToken) {
      return (this.authenticated = false);
    }

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

    if (!accessToken && 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 未过期之前)但是当我尝试刷新我的私人页面时,它会返回到 loginRegister 页面 在此处输入图片说明

cookie 也存在: 在此处输入图片说明

更新

我忘了添加我的 loginHandler 和 Privatescreen 路由:

路线

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;

loginHandler我里面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

事实证明我仍然登录,如果我http://localhost:3000/在浏览器中手动输入我的私人 URL(即),它允许我访问它,只是,每当我的 cookie 过期Auth.isAuthenticated()undefined,我就会被推回/loginRegister路由。我该怎么做才能使它true而不是undefined.

更新 3

添加图像以更好地理解:

  1. 登录后,我的保护路径立即生效,并打开了私人屏幕。 在此处输入图片说明

  2. 当我的访问令牌过期 30 秒后,如果我刷新页面,我会推回/loginRegister路由,因为它的某些方式Auth.isAuthenticated()未定义。 在此处输入图片说明

  3. 只有当我再次手动输入URL并输入时,它才会转到私有路由: 在此处输入图片说明

更新 4

获取错误未定义 在此处输入图片说明

1个回答

在 Auth.js 中,您在声明新的 accessToken 后不会返回任何内容。你可以像下面那样在那里返回 true ;

...
 if (!accessToken && 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);
        });
    }