Next.js 13如何实现路由保护?解决req.page缺失及闪屏问题
Next.js 13 路由保护方案(适配动态路由场景)
方案1:使用中间件(Middleware)全局拦截
Next.js 13 App Router 官方推荐用中间件实现路由保护,它能在页面渲染前执行逻辑,完美处理 /user/[id] 这类动态路由,还能彻底避免内容闪屏。
- 实现步骤:
- 在项目根目录创建
middleware.ts(或.js)文件 - 借助
NextRequest和NextResponse检测认证状态、匹配目标路由 - 示例代码:
import { NextRequest, NextResponse } from 'next/server'; export function middleware(request: NextRequest) { // 从Cookie/Session等获取真实认证状态,这里仅做示例 const isAuthenticated = request.cookies.get('auth-token')?.value; // 定义需要保护的路由,支持动态路由通配符 const protectedRoutes = ['/about', '/user', '/user/:id*']; // 校验当前请求是否命中保护路由 const matchesProtectedRoute = protectedRoutes.some(route => { const routeRegex = new RegExp(`^${route.replace(':id*', '.*')}$`); return routeRegex.test(request.nextUrl.pathname); }); if (matchesProtectedRoute && !isAuthenticated) { // 未认证则重定向至登录页,替换为你的实际登录路由 return NextResponse.redirect(new URL('/login', request.url)); } // 认证通过或路由无需保护,继续处理请求 return NextResponse.next(); } // 指定中间件生效的路由范围,可进一步缩小拦截范围 export const config = { matcher: ['/about', '/user/:path*'], };
- 在项目根目录创建
方案2:Server Components 页面内直接校验
如果使用App Router的Server Components,可在页面组件中直接做认证检查并触发重定向——Server Components在服务器端渲染,不会在客户端暴露未授权内容,自然不会有闪屏问题。
- 示例(
/user/[id]/page.tsx):import { redirect } from 'next/navigation'; // 假设用NextAuth处理认证,可替换为自定义的认证逻辑 import { getServerSession } from 'next-auth/next'; import { authOptions } from '@/app/api/auth/[...nextauth]/route'; export default async function UserProfilePage({ params }: { params: { id: string } }) { const session = await getServerSession(authOptions); if (!session) { redirect('/login'); } // 这里可通过params.id获取动态路由的slug,正常处理页面逻辑 return <div>用户ID:{params.id} 的个人页面</div>; }
方案3:Client Components 避免闪屏的处理方式
如果必须使用Client Components,要避免闪屏,需先完成认证状态校验,再渲染页面核心内容:
- 示例:
'use client'; import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { getSession } from 'next-auth/react'; export default function UserProfilePage({ params }: { params: { id: string } }) { const router = useRouter(); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const checkAuthStatus = async () => { const session = await getSession(); if (!session) { router.push('/login'); } setIsLoading(false); }; checkAuthStatus(); }, [router]); // 认证校验完成前,仅显示加载态(如骨架屏),不渲染页面内容 if (isLoading) { return <div>加载中...</div>; } return <div>用户ID:{params.id} 的个人页面</div>; }
关于next-shield闪屏的原因
next-shield是在客户端层面做路由守卫,会先渲染页面内容,再触发认证检查和重定向,因此会出现短暂的内容闪屏。而上述中间件、Server Components方案都是在服务器端提前处理逻辑,从根源上避免了这个问题。
内容的提问来源于stack exchange,提问作者Farrukh Ahmad
相关产品推荐
相关产品推荐

