如何将客户端身份验证系统迁移至新App Router并实现登录校验跳转?
在Next.js App Router中实现登录状态校验与跳转
1. 服务器组件内直接校验(推荐,安全无信息泄露)
App Router的服务器组件可以直接在服务端执行登录校验逻辑,不会将敏感逻辑暴露给前端,是最安全的方案。
受保护页面示例(如仪表盘)
app/dashboard/page.tsx
import { redirect } from 'next/navigation'; // 自行封装的获取当前用户的函数(从Cookie/数据库校验会话) import { getCurrentUser } from '@/lib/auth'; export default async function DashboardPage() { const user = await getCurrentUser(); // 未登录则重定向到登录页 if (!user) { redirect('/login'); } return ( <div> <h1>用户仪表盘</h1> <p>欢迎回来,{user.nickname}</p> </div> ); }
登录页反向校验示例
app/login/page.tsx
import { redirect } from 'next/navigation'; import { getCurrentUser } from '@/lib/auth'; export default async function LoginPage() { const user = await getCurrentUser(); // 已登录用户访问登录页,直接跳转到仪表盘 if (user) { redirect('/dashboard'); } return ( <div> <h1>用户登录</h1> {/* 登录表单逻辑 */} </div> ); }
注:getCurrentUser需自行实现,比如从请求Cookie中读取会话ID,再去数据库校验有效性。
2. 全局中间件(Middleware)批量处理路由保护
如果多个页面都需要登录校验,用中间件可以避免重复代码,统一处理路由拦截。
创建app/middleware.ts:
import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; import { getCurrentUser } from '@/lib/auth'; export async function middleware(request: NextRequest) { const user = await getCurrentUser(); const path = request.nextUrl.pathname; // 定义需要登录才能访问的路由列表 const protectedPaths = ['/dashboard', '/profile', '/settings']; // 定义登录/注册类路由 const authPaths = ['/login', '/register']; // 未登录访问受保护路由 → 跳转登录页 if (protectedPaths.includes(path) && !user) { return NextResponse.redirect(new URL('/login', request.url)); } // 已登录访问登录/注册路由 → 跳转仪表盘 if (authPaths.includes(path) && user) { return NextResponse.redirect(new URL('/dashboard', request.url)); } // 其他情况正常放行 return NextResponse.next(); } // 指定中间件生效的路由范围 export const config = { matcher: ['/dashboard/:path*', '/profile/:path*', '/settings/:path*', '/login', '/register'], };
注:中间件运行在Edge Runtime,getCurrentUser需避免使用Node.js专属API,比如用request.cookies.get()读取会话Cookie。
3. 客户端组件内校验(适配动态交互场景)
如果是带交互逻辑的客户端组件(需加'use client'指令),可以用useRouter实现跳转:
'use client'; import { useEffect } from 'react'; import { useRouter } from 'next/navigation'; // 自定义Hook,用于在客户端获取用户状态(可结合SWR/React Query实现) import { useUser } from '@/hooks/useUser'; export default function ClientProtectedSection() { const { user, loading } = useUser(); const router = useRouter(); useEffect(() => { // 加载完成后判断用户状态,未登录则跳转 if (!loading && !user) { router.push('/login'); } }, [user, loading, router]); // 加载状态下显示占位符,避免页面闪屏 if (loading) { return <div>加载中...</div>; } return ( <div> <p>仅登录用户可见的动态内容</p> </div> ); }
关键注意事项
- 优先使用服务器端校验/中间件,避免前端先渲染敏感内容再跳转的闪屏问题
- 中间件适合全局路由规则,服务器组件适合单页定制化校验
- 客户端校验仅用于动态交互场景,需妥善处理加载状态
内容的提问来源于stack exchange,提问作者Henrique B
相关产品推荐
相关产品推荐

