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

Next-auth:设置请求头或Body时getSession返回null的问题

Next.js + NextAuth POST请求带Body/Header时getSession返回null的问题

问题现象

使用NextAuth实现认证时:

  • GET请求或不带Content-Type头、无Body的POST请求中,服务端调用await getSession({ req })能正常返回session数据
  • 当POST请求添加Content-Type: application/json头及JSON格式Body后,getSession返回null
  • 临时测试发现:先复制req.body再删除它,就能正常获取session

异常请求示例:

const response = await fetch("/api/shops", {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    shopName: shopName,
    description: description
  }),
});

NextAuth配置文件([...nextauth].js):

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import mongoDbClient from "../../../lib/mongodb";
import bcrypt from "bcryptjs";

export default NextAuth({
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "email", type: "text" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials, req) {
        const db = (await mongoDbClient).db(process.env.MONGODB_DBNAME);
        const usersCollection = db.collection("users");

        const user = await usersCollection.findOne({
          email: credentials.email,
        });

        if (user && bcrypt.compareSync(credentials.password, user.password)) {
          delete user.password;
          return user;
        } else {
          throw new Error('Invalid credentials');
        }
      },
    }),
  ],
  session: {
    jwt: true,
  },
  jwt: {
    secret: process.env.JWT_SECRET,
  },
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.user = user;
      }
      return token;
    },
  
    async session({ session, token }) {
      if (token.user) {
        session.user = token.user;
      }
      return session;
    },
  },
});

原因分析

这不属于预期行为,本质是Next.js API路由的自动body解析机制与NextAuth的getSession方法对req对象的处理冲突:

  • 当请求带有Content-Type: application/json时,Next.js会自动解析请求体并挂载到req.body,这个过程会修改req对象的内部状态(比如消耗请求流、修改可读状态)
  • NextAuth的getSession内部需要读取请求的原始头信息(包括认证cookie),但req被自动解析body后,部分内部状态变化导致NextAuth无法正确提取session数据

解决方案

方案1:先调用getSession再处理req.body

调整代码顺序,确保获取session的操作在读取req.body之前执行:

export default async function handler(req, res) {
  // 优先获取session
  const session = await getSession({ req });
  if (!session) {
    res.status(401).json({ error: "Unauthorized" });
    return;
  }

  // 再处理请求体
  const { shopName, description } = req.body;
  
  // 后续业务逻辑
  // ...
}

方案2:使用getToken替代getSession

由于你使用的是JWT模式的session,直接调用getToken方法可以绕过req.body解析的冲突,更直接地获取用户认证信息:

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

export default async function handler(req, res) {
  // 直接获取JWT token
  const token = await getToken({ req, secret: process.env.JWT_SECRET });
  if (!token) {
    res.status(401).json({ error: "Unauthorized" });
    return;
  }

  // token中包含用户信息,可直接使用
  const { shopName, description } = req.body;
  
  // 后续业务逻辑
  // ...
}

方案3:禁用自动body解析,手动解析

通过API路由配置禁用Next.js的自动body解析,手动处理请求体,避免req对象被提前修改:

// 禁用自动body解析
export const config = {
  api: {
    bodyParser: false,
  },
};

export default async function handler(req, res) {
  let body = {};
  // 手动解析JSON格式的请求体
  if (req.method === "POST" && req.headers["content-type"] === "application/json") {
    body = await new Promise((resolve, reject) => {
      let rawData = "";
      req.on("data", (chunk) => (rawData += chunk));
      req.on("end", () => {
        try {
          resolve(JSON.parse(rawData));
        } catch (err) {
          reject(err);
        }
      });
      req.on("error", reject);
    });
  }

  // 获取session
  const session = await getSession({ req });
  if (!session) {
    res.status(401).json({ error: "Unauthorized" });
    return;
  }

  // 使用解析后的body
  const { shopName, description } = body;
  
  // 后续业务逻辑
  // ...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 00:50:34