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

NextJS Middleware引发localhost重定向过多错误及路由保护方案咨询

解决NextAuth登出重定向循环及无中间件路由保护方案

一、修复中间件的重定向循环问题

你的重定向循环问题根源在于中间件拦截了NextAuth的内部认证路由(如/api/auth/signout),导致登出请求被强制跳转到登录页,打断了登出流程,进而引发循环。

修改后的middleware.ts代码如下:

import { NextRequest, NextResponse } from 'next/server'
import { getToken } from "next-auth/jwt"; // 补上缺失的导入

export default async function middleware(req: NextRequest) {
    const path = req.nextUrl.pathname;

    // 定义无需保护的公共路径:登录、注册、NextAuth内部路由
    const isPublicPath = ['/login', '/signup'].includes(path) || path.startsWith('/api/auth/');
    
    // 公共路径直接放行
    if (isPublicPath) {
        return NextResponse.next();
    }

    const session = await getToken({
        req,
        secret: process.env.NEXTAUTH_SECRET,
    });

    // 无会话时跳转到登录页
    if (!session) {
        return NextResponse.redirect(new URL('/login', req.url));
    }

    // 有会话时,若访问登录/注册页则跳转到首页
    if (session && ['/login', '/signup'].includes(path)) {
        return NextResponse.redirect(new URL('/', req.url));
    }

    return NextResponse.next();
}

关键改动:

  • 新增isPublicPath判断,排除NextAuth的/api/auth/*路由,确保登出等认证请求能正常处理
  • 先放行公共路径,再执行会话校验逻辑

二、不使用中间件实现全路由保护

方案1:App Router(Server Components)

利用Next.js Server Components的服务器端能力,直接在页面组件中校验会话:

import { getServerSession } from "next-auth/next";
import { authOptions } from "@/app/api/auth/[...nextauth]/route"; // 导入你的NextAuth配置
import { redirect } from "next/navigation";

export default async function ProtectedPage() {
  // 服务器端校验会话
  const session = await getServerSession(authOptions);
  
  if (!session) {
    // 无会话时重定向到登录页
    redirect("/login");
  }

  return (
    <div>
      <h1>受保护的页面内容</h1>
    </div>
  );
}

你可以将这段校验逻辑封装成公共布局组件,所有需要保护的页面复用该布局即可。

方案2:Pages Router(高阶组件HOC)

在Pages Router中,通过高阶组件统一处理会话校验:

// utils/withAuth.ts
import { useSession } from "next-auth/react";
import { useEffect } from "react";
import { useRouter } from "next/router";

// 高阶组件:包装需要保护的页面组件
export function withAuth<T extends {}>(Component: React.ComponentType<T>) {
  return function ProtectedComponent(props: T) {
    const { data: session, status } = useSession();
    const router = useRouter();

    useEffect(() => {
      // 会话未认证时跳转到登录页
      if (status === "unauthenticated") {
        router.push("/login");
      }
    }, [status, router]);

    // 会话校验中显示加载状态
    if (status === "loading") {
      return <div>加载中...</div>;
    }

    return <Component {...props} />;
  };
}

在需要保护的页面组件中使用:

// pages/protected.tsx
import { withAuth } from "../utils/withAuth";

function ProtectedPage() {
  return <h1>受保护的页面内容</h1>;
}

export default withAuth(ProtectedPage);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:15:36