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

Next-Auth getSession在middleware.js中返回null的问题求助

解决Next-Auth Middleware中getSession返回null的问题

核心问题分析

  1. 导入错误:你在middleware中使用的getSession来自next-auth/react,这个方法是为客户端React组件设计的,无法在Edge Runtime环境的middleware中正确获取会话。
  2. Middleware冲突:同时导出默认的next-auth/middleware和自定义middleware会导致Next.js只执行其中一个,逻辑无法正常触发。

步骤1:抽离NextAuth配置

修改[...nextauth].js,将认证配置单独导出,方便middleware复用:

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcryptjs";
import { connectDB } from "@/backend/utils/dbConnect";
import prisma from "@/prisma/prismaClient";

// 单独导出auth配置
export const authOptions = {
  providers: [
    CredentialsProvider({
      name: "credentials",
      credentials: {},
      async authorize(credentials, req) {
        const { identifier, password } = credentials;
        try {
          await connectDB();
          const user = await prisma.users.findFirst({
            where: {
              OR: [{ email: identifier }, { phone: identifier }],
            },
          });
          if (!user) return null;
          const passwordMatching = await bcrypt.compare(password, user.password);
          return passwordMatching ? user : null;
        } catch (error) {
          return null;
        }
      },
    }),
  ],
  session: {
    strategy: "jwt",
    maxAge: 7 * 24 * 60 * 60,
    expires: 30 * 24 * 60 * 60,
  },
  callbacks: {
    async jwt({ token, user }) {
      if (user) token.user = user;
      return token;
    },
    async session({ session, token }) {
      session.user.id = token.user.id;
      session.user.role = token.user.role;
      delete session.user.email;
      delete session.user.phone;
      delete session.user.password;
      return session;
    },
  },
  pages: {
    signIn: "/login",
  },
  secret: process.env.NEXTAUTH_SECRET,
};

export const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

步骤2:重构Middleware代码

删除默认的next-auth middleware导出,改用getServerSession(服务端/Edge环境专用)获取会话,并完善跳转逻辑:

import { NextResponse } from "next/server";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/app/api/auth/[...nextauth]"; // 根据你的项目路径调整

export const config = {
  matcher: ["/admin/:path*", "/donor/:path*", "/login"],
};

const roleRedirects = {
  admin: "/admin",
  donor: "/donor",
};

export async function middleware(request) {
  const session = await getServerSession(authOptions);
  const role = session?.user?.role;
  const { pathname } = request.nextUrl;

  // 已登录用户访问登录页,跳转到对应角色仪表盘
  if (session && pathname === "/login") {
    return NextResponse.redirect(new URL(roleRedirects[role], request.url));
  }

  // 未登录用户访问权限页,跳转到登录页
  if (!session && (pathname.startsWith("/admin") || pathname.startsWith("/donor"))) {
    return NextResponse.redirect(new URL("/login", request.url));
  }

  // 已登录用户访问非自身角色的权限页,跳转到自己的仪表盘
  if (session && role) {
    const allowedPath = roleRedirects[role];
    if (!pathname.startsWith(allowedPath)) {
      return NextResponse.redirect(new URL(allowedPath, request.url));
    }
  }

  return NextResponse.next();
}

额外检查项

  1. 确保NEXTAUTH_SECRET环境变量已正确配置,JWT会话的解析依赖此密钥。
  2. 确认数据库返回的用户对象包含role字段,且在jwt和session回调中正确传递。
  3. 验证middleware文件路径是否符合Next.js要求:App Router项目中需放在根目录或app目录下。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 01:44:56