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

Next.js 13.5.2 API路由getServerSession返回null及报错求助

Next.js + Next-Auth 问题解决:API路由会话获取失败及请求错误

问题现象

  • API路由中调用getServerSession(authOptions)始终返回null,但Server组件和Client组件分别通过getServerSession和useSession()能正常获取会话
  • 调用创建待办的API接口时出现错误:⨯ TypeError: Response body object should not be disturbed or locked at extractBody

相关代码

Next-Auth配置

import { authOptions } from '@/lib/auth-options'
import NextAuth from 'next-auth'

const handler = NextAuth(authOptions)

export {handler as GET,handler as POST}

authOptions配置

import { type NextAuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github";
import { getAuthCredentials } from "./secrets";
export const authOptions: NextAuthOptions = {
  providers: [
    GithubProvider({
      clientId: getAuthCredentials().clientId,
      clientSecret: getAuthCredentials().clientSecret,
    }),
  ],
  secret: getAuthCredentials().secret,
  session: {
    strategy: "jwt",
  },
  callbacks: {
    jwt: ({ token, user, session }) => {
      if (user) {
        token.id = user.id;
      }
      return token;
    },
    session: ({ session, token }) => {
      if (token?.id) {
        session.user.id = token.id;
      }
      return session;
    },
  },
  pages: {
    signIn: "/signin",
    signOut: "/signout",
  },
};

创建待办的API路由(api/todos)

export async function POST(req: NextRequest) {
  let body = await req.json();
  const session = await getServerSession(authOptions);
  console.log({ session });
  // {session : null}
  let validateBody = addTodoSchema.safeParse(body);
  console.log({ validateBody });
  if (!validateBody.success) {
    return NextResponse.json({
      success: false,
      error: validateBody.error,
    });
  }
  try {
    await connectToDatabase();
    let todo = await prisma.todo.create({
      data: {
        ...body,
        createdBy: session?.user.id,
      },
    });
    return NextResponse.json({
      success: true,
      data: todo,
      message: "Todo created successfully",
    });
  } catch (error: any) {
    console.log({ error });
    return NextResponse.json({
      success: false,
      error: error.message,
    });
  } finally {
    await prisma.$disconnect();
  }
}

调用接口的服务端函数

"use server";
import { headers } from "next/headers";
export const addTodo = async ({ title }: { title: string }) => {
  try {
    let res = await fetch("http://localhost:3000/api/todos", {
      method: "POST",
      headers: headers(),
      body: JSON.stringify({
        title,
      }),
    });
    let data = await res.json();
    console.log({ data });
  } catch (error: any) {
    console.log({ error });
    // throw new Error(error.message);
  }
};

解决方案

1. 修复API路由getServerSession返回null的问题

问题根源在于服务端函数传递了所有请求头,其中包含Next.js内部非标准头,导致Next-Auth无法正确解析会话。只需传递必要的Cookie头即可:

修改调用接口的服务端函数:

"use server";
import { cookies } from "next/headers";
export const addTodo = async ({ title }: { title: string }) => {
  try {
    const cookieStore = cookies();
    let res = await fetch("http://localhost:3000/api/todos", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Cookie": cookieStore.toString()
      },
      body: JSON.stringify({ title }),
    });
    let data = await res.json();
    console.log({ data });
  } catch (error: any) {
    console.log({ error });
  }
};

同时确保authOptions中的secret与环境变量完全一致,JWT会话解析依赖该密钥。

2. 修复Response body锁定错误

该错误是由于传递多余请求头导致请求体解析异常,上述修改headers的操作已解决此问题。另外注意在API路由中只读取一次请求体(你的代码已做到),避免重复调用req.json()。

额外优化

  • 移除API路由finally块中的prisma.$disconnect(),Prisma会自动管理连接池,手动断开会降低性能。
  • 在API路由中增加未授权判断,提前终止逻辑:
const session = await getServerSession(authOptions);
if (!session) {
  return NextResponse.json(
    { success: false, error: "Unauthorized" },
    { status: 401 }
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:23:17