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

Next.js 13中调用redirect跳转时触发NEXT_REDIRECT错误排查

问题分析与解决方法

错误原因

  1. 在服务端组件中使用客户端鉴权监听:你的Home组件是异步函数,在Next.js App Router中默认属于服务端组件。而onAuthStateChanged是Firebase的客户端API,依赖浏览器环境运行,不能在服务端组件中调用。
  2. 在异步回调中调用redirect():Next.js的redirect()函数必须在组件初始渲染流程中执行。但onAuthStateChanged的回调是异步触发的,会在组件开始渲染后才运行,此时调用redirect()就会抛出NEXT_REDIRECT错误。

修复方案(客户端组件实现)

将组件标记为客户端组件,使用React状态跟踪用户鉴权状态,并通过useRouter完成重定向:

'use client';

import { useEffect, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from '../src/firebaseConfig';
import { useRouter } from 'next/navigation';

export default function Home() {
  const [user, setUser] = useState(null);
  const router = useRouter();

  useEffect(() => {
    // 订阅鉴权状态变化
    const unsubscribe = onAuthStateChanged(auth, (authUser) => {
      setUser(authUser);
      if (!authUser) {
        router.replace('/login');
      }
    });

    // 组件卸载时取消订阅,避免内存泄漏
    return unsubscribe;
  }, [router]);

  // 鉴权状态未确定时显示加载中
  if (user === null) {
    return <div>加载中...</div>;
  }

  // 已登录用户的页面内容
  return (
    <div>
      <h1>首页</h1>
      <p>欢迎回来,{user.email}!</p>
    </div>
  );
}

更安全的方案(服务端中间件)

如果需要更高的安全性,建议使用Next.js中间件在服务端提前校验用户身份,避免客户端鉴权被绕过:

创建项目根目录下的middleware.ts文件:

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { getAuth } from 'firebase-admin/auth';
import { initializeApp, getApps } from 'firebase-admin/app';

// 初始化Firebase Admin SDK(仅初始化一次)
if (!getApps().length) {
  initializeApp({
    credential: getAuth().credential.cert({
      projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
      clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
      privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
    }),
  });
}

export async function middleware(request: NextRequest) {
  // 获取客户端存储的会话Cookie
  const sessionCookie = request.cookies.get('__session')?.value;

  try {
    if (sessionCookie) {
      // 校验会话Cookie的有效性
      await getAuth().verifySessionCookie(sessionCookie, true);
      // 校验通过,允许访问页面
      return NextResponse.next();
    }
  } catch (err) {
    // Cookie无效,重定向到登录页
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // 无有效会话,重定向到登录页
  return NextResponse.redirect(new URL('/login', request.url));
}

// 指定需要保护的路由
export const config = {
  matcher: ['/', '/dashboard/:path*'], // 添加你的受保护路由
};

注意:使用中间件方案时,需要在客户端登录后通过API路由创建并设置会话Cookie,具体可参考Firebase官方文档中关于会话Cookie的说明。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 16:05:43