如何使用React+Next.js防止未登录用户访问内部页面
Next.js 实现未登录用户自动重定向到登录页
基于你当前用sessionStorage存储登录状态的逻辑,下面分两种主流路由方案给出实现方式:
一、Pages Router(传统路由)
方法:封装鉴权高阶组件(HOC)
创建一个通用的鉴权组件,所有需要登录才能访问的页面都用它包裹:
// components/RequireAuth.tsx import { useEffect } from 'react'; import { useRouter } from 'next/router'; const RequireAuth = ({ children }: { children: React.ReactNode }) => { const router = useRouter(); useEffect(() => { // 检查sessionStorage中的登录标识 const email = sessionStorage.getItem('email'); if (!email) { // 未登录则重定向到登录页 router.push('/index/login'); } }, [router]); return children; }; export default RequireAuth;
在需要保护的页面(比如pages/dashboard.tsx)中使用:
// pages/dashboard.tsx import RequireAuth from '../components/RequireAuth'; const Dashboard = () => { return <div>仪表盘页面</div>; }; export default RequireAuth(Dashboard);
补充:服务端鉴权(可选)
如果你的登录状态存在服务端会话(比如Cookie),可以在页面的getServerSideProps中验证,避免客户端渲染时的页面闪烁:
// pages/dashboard.tsx export async function getServerSideProps(context: any) { const { req } = context; // 从Cookie中读取登录状态(根据实际存储方式调整) const email = req.cookies.email; if (!email) { return { redirect: { destination: '/index/login', permanent: false, }, }; } return { props: {} }; }
二、App Router(App目录路由)
方法1:客户端组件鉴权布局
创建一个客户端组件作为鉴权布局,将所有需要保护的页面放在同一个目录下并使用该布局:
// app/(protected)/layout.tsx 'use client'; import { useEffect } from 'react'; import { useRouter } from 'next/navigation'; export default function ProtectedLayout({ children }: { children: React.ReactNode }) { const router = useRouter(); useEffect(() => { const email = sessionStorage.getItem('email'); if (!email) { router.push('/index/login'); } }, [router]); return <>{children}</>; }
把所有内部页面(比如dashboard、profile)放在app/(protected)目录下,访问这些页面时会自动触发鉴权逻辑。
方法2:Middleware中间件(适合服务端会话)
如果登录状态存储在服务端(比如Cookie),可以用Middleware做全局鉴权,拦截未登录请求:
// middleware.ts import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { // 排除登录页和静态资源路径 if (request.nextUrl.pathname.startsWith('/index/login') || request.nextUrl.pathname.startsWith('/_next')) { return NextResponse.next(); } // 从Cookie中读取登录状态 const email = request.cookies.get('email')?.value; if (!email) { // 未登录则重定向到登录页 return NextResponse.redirect(new URL('/index/login', request.url)); } } // 指定需要鉴权的路由规则 export const config = { matcher: ['/dashboard/:path*', '/profile/:path*'], // 替换为你的内部页面路由 };
登出逻辑补充
记得在登出时清除sessionStorage中的登录状态:
const handleLogout = () => { sessionStorage.removeItem('email'); router.push('/index/login'); };
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

