Next.js中间件引发客户端导航认证无限重定向循环问题
问题原因分析
- Cookie路径配置错误:如果登录接口设置
sessioncookie时未指定Path=/,浏览器会默认将cookie路径设为/api,导致/dashboard路径的请求无法携带该cookie,中间件检测不到session就会触发重定向。 - 登录页缺少已登录状态判断:用户登录后被重定向到
/dashboard,若中间件因cookie问题触发重定向回/login,而/login页面没有自动跳转逻辑,用户可能重复触发登录操作,形成循环。 - 中间件Matcher范围不合理:原Matcher匹配所有非login路径,虽逻辑上没问题,但扩大了中间件运行范围,若配合cookie路径问题,更容易引发异常重定向。
解决方案
1. 修正登录接口的Cookie设置
确保在/api/login接口中设置cookie时指定Path=/,让所有路径的请求都能携带该cookie:
// pages/api/login.ts import type { NextApiRequest, NextApiResponse } from 'next'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { // 执行登录验证逻辑... // 设置session cookie,强制指定路径为根目录 res.setHeader('Set-Cookie', [ `session=your-session-id; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=86400` ]); res.status(200).json({ success: true }); }
2. 调整中间件逻辑与Matcher配置
缩小中间件运行范围,同时添加已登录用户访问/login时的自动跳转:
// middleware.ts import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const sessionCookie = request.cookies.get('session'); const { pathname } = request.nextUrl; const isProtectedRoute = pathname.startsWith('/dashboard'); const isLoginRoute = pathname === '/login'; // 未登录访问受保护路由 → 重定向到登录页 if (!sessionCookie && isProtectedRoute) { return NextResponse.redirect(new URL('/login', request.url)); } // 已登录访问登录页 → 自动跳转到仪表盘 if (sessionCookie && isLoginRoute) { return NextResponse.redirect(new URL('/dashboard', request.url)); } return NextResponse.next(); } // 仅匹配受保护路由和登录页,减少中间件不必要的运行 export const config = { matcher: ['/dashboard/:path*', '/login'], };
3. 优化登录页的跳转逻辑
添加已登录状态检测,避免重复操作:
// pages/login.tsx import { useEffect } from 'react'; import { useRouter } from 'next/router'; const LoginPage = () => { const router = useRouter(); useEffect(() => { // 调用接口检查登录状态(HttpOnly cookie无法在客户端直接读取) const checkSession = async () => { const res = await fetch('/api/check-session'); const data = await res.json(); if (data.isLoggedIn) { router.push('/dashboard'); } }; checkSession(); }, [router]); const handleLogin = async () => { await fetch('/api/login', { method: 'POST', credentials: 'same-origin' }); router.push('/dashboard'); // 使用Next.js Router跳转,而非window.location.href }; return ( <div> <button onClick={handleLogin}>登录</button> </div> ); }; export default LoginPage;
4. 补充会话检查接口
用于登录页验证用户状态:
// pages/api/check-session.ts import type { NextApiRequest, NextApiResponse } from 'next'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { const sessionCookie = req.cookies.session; // 这里可以添加session有效性校验逻辑 res.status(200).json({ isLoggedIn: !!sessionCookie }); }
关键验证步骤
- 在浏览器Application面板中查看
sessioncookie的Path是否为/。 - 在中间件中添加
console.log('Session cookie:', sessionCookie),确认请求是否携带cookie。 - 测试客户端导航(
Link组件)和全页面刷新两种场景,确认重定向逻辑正常。
内容的提问来源于stack exchange,提问作者ahtisham ali
相关产品推荐
相关产品推荐

