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

如何在NextJS13+NextAuth+t3栈中实现无会话用户重定向?

针对T3栈未登录重定向的正确实现方案

你遇到的NEXT_REDIRECT错误,是因为直接在客户端组件中调用了Next.js App Router的服务端专属redirect函数——useSession属于客户端钩子,调用它的组件会被标记为客户端组件,而服务端函数不能在客户端环境中执行。

以下是基于T3初始项目的几种可行方案:

方案1:App Router服务端组件实现(推荐)

将页面改为纯服务端组件,在服务端直接获取Session并处理重定向,避免客户端渲染闪烁:

// app/protected/page.tsx
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/server/auth";
import { redirect } from "next/navigation";

export default async function ProtectedPage() {
  const session = await getServerSession(authOptions);

  if (!session) {
    redirect("/auth/signin"); // 可替换为首页路径
  }

  return <div>Test</div>;
}

注意:该组件不能包含任何客户端钩子(如useSession),如果需要交互逻辑,嵌套客户端组件即可。

方案2:App Router客户端组件实现

若必须使用客户端组件,改用useRouter配合useEffect实现重定向:

// app/protected/page.tsx
"use client";

import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useEffect } from "react";

export default function ProtectedPage() {
  const { data: session, status } = useSession();
  const router = useRouter();

  useEffect(() => {
    // 等待Session状态加载完成后再判断,避免初始null导致误重定向
    if (status === "unauthenticated") {
      router.push("/auth/signin");
    }
  }, [status, router]);

  // 加载状态时展示过渡组件
  if (status === "loading") {
    return <div>加载中...</div>;
  }

  // 未登录时不渲染页面内容
  if (!session) {
    return null;
  }

  return <div>Test</div>;
}

方案3:Pages Router项目实现

如果你的T3项目使用旧版Pages Router,在页面的getServerSideProps中处理服务端重定向:

// pages/protected.tsx
import { GetServerSideProps, NextPage } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../server/auth";
import { useSession } from "next-auth/react";

const ProtectedPage: NextPage = () => {
  const { data: session } = useSession();
  return <div>Test</div>;
};

export const getServerSideProps: GetServerSideProps = async (context) => {
  const session = await getServerSession(context.req, context.res, authOptions);

  if (!session) {
    return {
      redirect: {
        destination: "/auth/signin",
        permanent: false,
      },
    };
  }

  return { props: {} };
};

export default ProtectedPage;

批量路由保护:NextAuth Middleware

如果需要保护多个路由,推荐使用NextAuth Middleware实现全局拦截,无需每个页面单独编写逻辑:

// middleware.ts
import { withAuth } from "next-auth/middleware";

export default withAuth({
  pages: {
    signIn: "/auth/signin", // 未登录时重定向的目标页
  },
});

// 配置需要保护的路由规则
export const config = {
  matcher: ["/protected/:path*", "/dashboard/:path*"], // 匹配所有需要拦截的路由
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 12:12:25