You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中间件引发客户端导航认证无限重定向循环问题

问题原因分析

  1. Cookie路径配置错误:如果登录接口设置session cookie时未指定Path=/,浏览器会默认将cookie路径设为/api,导致/dashboard路径的请求无法携带该cookie,中间件检测不到session就会触发重定向。
  2. 登录页缺少已登录状态判断:用户登录后被重定向到/dashboard,若中间件因cookie问题触发重定向回/login,而/login页面没有自动跳转逻辑,用户可能重复触发登录操作,形成循环。
  3. 中间件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 });
}

关键验证步骤

  1. 在浏览器Application面板中查看session cookie的Path是否为/。
  2. 在中间件中添加console.log('Session cookie:', sessionCookie),确认请求是否携带cookie。
  3. 测试客户端导航(Link组件)和全页面刷新两种场景,确认重定向逻辑正常。

内容的提问来源于stack exchange,提问作者ahtisham ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 14:55:58