NextAuth.js + Next.js App Router:如何在中间件中检查用户是否完成引导?
解决NextAuth中间件中检查引导状态的问题
为什么getServerSession会报错?
getServerSession是为Node.js环境的服务器组件/API路由设计的,而Next.js的Middleware运行在边缘Runtime,不支持Node.js专属API,因此无法在Middleware中使用getServerSession,必须改用NextAuth提供的边缘兼容方式获取Session。
正确实现引导状态检查的步骤
1. 自定义NextAuth Middleware(替换原默认导出)
不用直接导出NextAuth的默认Middleware,而是用withAuth包装自定义逻辑,通过req.nextauth获取Session/Token:
import { withAuth } from "next-auth/middleware"; import { NextResponse } from "next/server"; export default withAuth( async function middleware(req) { const { pathname } = req.nextUrl; // 从NextAuth上下文获取Session/Token(v4版本通常用req.nextauth.token) const session = req.nextauth.session || req.nextauth.token; // 检查用户是否完成引导(假设Session中已携带onboardingCompleted字段) const hasCompletedOnboarding = session?.user?.onboardingCompleted; // 路由重定向逻辑 // 已登录但未完成引导,且当前不在引导页 → 跳转到引导页 if (session && !hasCompletedOnboarding && pathname !== "/onBoarding") { return NextResponse.redirect(new URL("/onBoarding", req.url)); } // 已完成引导的用户访问引导页 → 跳转到主页 if (session && hasCompletedOnboarding && pathname === "/onBoarding") { return NextResponse.redirect(new URL("/", req.url)); } }, { // 授权回调:返回true表示用户已登录,进入自定义Middleware逻辑 callbacks: { authorized: ({ token }) => !!token, }, } ); // 路由匹配规则:排除API和登录页,其他路由都需检查 export const config = { matcher: ["/((?!api|login).*)"], };
2. 将引导状态同步到Session中
为了在Middleware中直接获取引导状态,需要在NextAuth的authOptions里配置jwt和session回调,从MongoDB查询并同步状态到Session:
// authOptions.js(你的NextAuth配置文件) import { User } from "@/models/User"; // 你的MongoDB用户模型 export const authOptions = { // 其他配置(providers、secret等)... callbacks: { async jwt({ token, user }) { // 用户首次登录时,从数据库获取引导状态 if (user) { const dbUser = await User.findById(user.id); token.onboardingCompleted = dbUser?.onboardingCompleted || false; } return token; }, async session({ session, token }) { // 将Token中的引导状态同步到Session,供Middleware使用 session.user.onboardingCompleted = token.onboardingCompleted; return session; }, }, };
3. (可选)直接在Middleware中查询MongoDB(不推荐)
如果不想把状态存在Session里,也可以在Middleware中调用内部API查询MongoDB(注意边缘环境的缓存限制):
// 在Middleware中添加查询函数 async function checkOnboardingStatus(userId) { const res = await fetch(`${process.env.NEXT_PUBLIC_APP_URL}/api/check-onboarding`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ userId }), cache: "no-store", // 禁用缓存,确保获取最新状态 }); const data = await res.json(); return data.completed; } // 在Middleware逻辑中调用 const hasCompletedOnboarding = await checkOnboardingStatus(session.sub);
原pages.newUser配置的替代
NextAuth v4中,pages.newUser已被弃用,改用上述Middleware逻辑实现首次登录后的引导页跳转。
内容的提问来源于stack exchange,提问作者rohit
相关产品推荐
相关产品推荐

