如何避免未登录的用户看到登录用户的页面? 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
中。
我正在使用 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
中。