如何避免未登录的用户看到登录用户的页面? Next JS客户端认证

How to avoid unlogged users to see pages for logged in users? Next JS Client side authentication

我正在使用 localStorage 在客户端处理我的应用程序身份验证,如果 localStorage 中没有“用户”项,则表示此人未登录,应该被重定向到 /login 页面。

问题是,例如,某人第一次访问根页面且未登录时,该人将能够看到 1 或 2 秒的“/”主页内容,这应该只有登录的用户才能看到,然后,用户将被重定向到“/login”进行身份验证。

我知道为什么会这样,但我想知道是否有更好的方法来避免这个恼人的小问题。

这是我的 login.js 页面代码:

import React from "react";
import Image from "next/image";

import GoogleLogin from "react-google-login";
import { FcGoogle } from "react-icons/fc";

import { useRouter } from "next/router";

import axios from "axios";

const Login = () => {
  const router = useRouter();

  const apiUserLogin = async (userName, userId, userImage) => {
    try {
      axios.post(
        `/api/users/login?name=${userName}&googleId=${userId}&imageUrl=${userImage}`
      );
    } catch (error) {
      console.log(error);
    }
  };

  const responseGoogle = (response) => {
    localStorage.setItem("user", JSON.stringify(response.profileObj));

    const { name, googleId, imageUrl } = response.profileObj;

    apiUserLogin(name, googleId, imageUrl).then(() => {
      router.push("/");
    });
  };

  return (
    <div className="flex flex-col items-center justify-center h-screen bg-black">
      <video
        src="/PostItvideo2.mp4"
        type="video/mp4"
        loop
        controls={false}
        muted
        autoPlay
        className="object-cover w-full h-full brightness-50"
      />

      <div className="absolute top-0 bottom-0 left-0 right-0 flex flex-col items-center justify-center">
        <div className="p-3">
          <Image
            src="/Postit-logofull.svg"
            width={140}
            height={80}
            alt="logo"
          />
        </div>

        <GoogleLogin
          clientId={`${process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID}`}
          render={(renderProps) => (
            <button
              type="button"
              className="flex items-center justify-center px-8 py-3 text-lg font-bold text-black bg-white border-none rounded-lg outline-none cursor-pointer"
              onClick={renderProps.onClick}
            >
              <FcGoogle size={21} className="mr-2" /> Sign in with Google
            </button>
          )}
          onSuccess={responseGoogle}
          onFailure={responseGoogle}
          cookiePolicy="single_host_origin"
        />
      </div>
    </div>
  );
};

export default Login; 

这是我的 _app.js 代码,这是“如果未登录则重定向”发生的地方:

import React, { useEffect } from "react";
import { AppContext } from "../context/context";
import { useRouter } from "next/router";

import "../styles/globals.css";

function MyApp({ Component, pageProps }) {
  const router = useRouter();

  useEffect(() => {
    const userInfo =
      localStorage.getItem("user") !== "undefined"
        ? JSON.parse(localStorage.getItem("user"))
        : null;

    if (router.pathname !== "/login" && !userInfo) router.push("/login");
  }, []);

  return (
    <AppContext>
      <Component {...pageProps} />
    </AppContext>
  );
}

export default MyApp;

通常会有一个加载屏幕。

function MyApp({ Component, pageProps }) {
  const router = useRouter();
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const userInfo = GET_USER_FROM_LS;
    if (router.pathname !== "/login" && !userInfo) {
     router.push("/login");
    } else {
     setIsLoading(false)
    }
  }, []);

  if(isLoading) {
   return <YourLoadingComponent />
  }

  return YOUR_DEFAULT_RETURN;
}

我个人尽量保持 _app 干净,所以我可能会将所有登录逻辑放在 AppContext 中。