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

NextAuth登录后按条件重定向及useSession获取session异常问题

问题原因分析

你遇到的useSession()先返回undefined后变为null的问题,核心原因是SignIn回调直接返回路径字符串时,NextAuth.js会跳过完整的Session创建流程——它只执行重定向,但不会在客户端正确初始化Session状态,导致useSession()无法获取到有效会话。

正确实现方案

步骤1:修复AuthOptions配置,完善Session字段传递

首先需要把accountComplete字段同步到JWT和Session中,同时让SignIn回调返回true(完成Session创建),而非直接返回重定向路径:

callbacks: {
    async jwt({ token, user }) {
      // 首次登录时,从数据库拉取用户完整信息同步到JWT
      if (user) {
        const currentUser = await prisma.user.findUnique({
          where: { id: user.id },
          select: { id: true, role: true, accountComplete: true }
        });
        return { ...token, ...currentUser };
      }
      return token;
    },
    async session({ session, token }) {
      // 将JWT中的字段同步到Session对象,供客户端调用
      session.user.id = token.id;
      session.user.role = token.role;
      session.user.accountComplete = token.accountComplete;
      return session;
    },
    async signIn({ user }) {
      // 仅验证用户是否允许登录,不直接返回路径
      const currentUser = await prisma.user.findUnique({
        where: { id: user.id },
      });
      // 异常情况:用户不存在则拒绝登录
      if (!currentUser) return false;
      // 允许登录,后续在客户端/服务端处理重定向
      return true;
    },
  },

步骤2:客户端/服务端处理条件重定向

方案A:组件内监听Session状态(适用于简单场景)

在根布局或应用入口组件中,监听Session加载状态,完成后执行重定向:

import { useSession } from "next-auth/react";
import { useEffect } from "react";
import { useRouter } from "next/navigation"; // App Router 版本
// import { useRouter } from "next/router"; // Pages Router 版本

export default function RootLayout({ children }) {
  const { data: session, status } = useSession({ required: false });
  const router = useRouter();

  useEffect(() => {
    // 仅当Session加载完成且有效时判断
    if (status === "authenticated") {
      const targetPath = session.user.accountComplete 
        ? "/" 
        : `/profile/edit/${session.user.id}`;
      // 避免重复重定向
      if (router.pathname !== targetPath) {
        router.push(targetPath);
      }
    }
  }, [session, status, router]);

  return (
    <html lang="zh-CN">
      <body>{children}</body>
    </html>
  );
}

方案B:用Middleware全局拦截(更推荐)

创建app/middleware.js,在服务器端统一处理路由重定向,避免客户端页面闪烁:

import { getToken } from "next-auth/jwt";
import { NextResponse } from "next/server";

export async function middleware(req) {
  const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });
  const { pathname } = req.nextUrl;

  // 已登录用户访问登录页,直接跳转到对应目标页
  if (token && pathname === "/auth/signin") {
    const target = token.accountComplete 
      ? "/" 
      : `/profile/edit/${token.id}`;
    return NextResponse.redirect(new URL(target, req.url));
  }

  // 未完善资料的用户尝试访问仪表盘,强制跳转到编辑页
  if (token && !token.accountComplete && pathname === "/") {
    return NextResponse.redirect(new URL(`/profile/edit/${token.id}`, req.url));
  }

  return NextResponse.next();
}

// 指定需要拦截的路由范围
export const config = {
  matcher: ["/auth/signin", "/", "/profile/edit/:id*"],
};
关键注意点
  • SignIn回调返回字符串路径是NextAuth.js的特殊逻辑,仅用于OAuth第三方登录后的跳转,不适用于需要保留Session的场景,必须返回true/false来完成完整的Session创建流程。
  • 务必在JWT和Session回调中同步accountComplete字段,确保客户端能获取到该状态做判断。
  • Middleware方案在服务器端处理,性能更优且不会出现客户端页面闪烁问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:30:18