NextAuth搭配MongoDB刷新页面即登出问题求助
问题原因与解决方法
你的核心问题是服务器端获取会话的方式错误:直接从ctx.req.session读取会话是无效的,NextAuth 要求在服务器端必须通过getServerSession方法来解析并验证会话(尤其是JWT策略下)。
具体修复步骤
1. 导入必要依赖
在authmiddleware.ts和使用中间件的页面中,导入getServerSession和你的NextAuth配置:
// authmiddleware.ts import { getServerSession } from "next-auth/next"; import { options } from "../pages/api/auth/[...nextauth]"; // 路径需匹配你的文件位置 import { GetServerSidePropsContext } from "next";
2. 修改中间件逻辑
把直接读取req.session的代码替换为getServerSession调用:
// authmiddleware.ts export async function isLoggedInMiddleware(ctx: GetServerSidePropsContext) { const session = await getServerSession(ctx.req, ctx.res, options); if (!session || !session.user) { ctx.res.writeHead(302, { Location: "/login" }); ctx.res.end(); return; } } export async function isLoggedOutMiddleware(ctx: GetServerSidePropsContext) { const session = await getServerSession(ctx.req, ctx.res, options); if (session) { ctx.res.writeHead(302, { Location: "/" }); ctx.res.end(); return; } }
3. 更新页面的getServerSideProps
因为中间件现在是异步函数,getServerSideProps需要加上await调用:
// Login.tsx export const getServerSideProps: GetServerSideProps<Props> = async (ctx) => { await isLoggedOutMiddleware(ctx); return { props: {}, }; }; // index.tsx export const getServerSideProps: GetServerSideProps<Props> = async (ctx) => { await isLoggedInMiddleware(ctx); // 可选:将会话传递给页面props,让SessionProvider在服务端渲染时就能拿到会话 const session = await getServerSession(ctx.req, ctx.res, options); return { props: { session }, }; };
4. 额外检查项
- 确保
NEXTAUTH_SECRET环境变量已正确设置:生产环境必须使用安全的随机字符串,可用openssl rand -hex 32生成,不能用默认值。 - 登录逻辑优化:当前用
setTimeout跳转不够可靠,建议直接设置signIn的redirect: true,让NextAuth自动处理跳转:
登录成功后会自动跳转到首页,无需手动调用// Login.tsx 中handleLogin修改 const response = await signIn("credentials", { redirect: true, callbackUrl: "/", username, password })router.push。
原理说明
当使用CredentialsProvider + JWT会话策略时,NextAuth不会自动在req.session中填充数据,必须通过getServerSession验证请求中的JWT令牌、解析出有效会话。直接读取req.session会拿到空值,导致刷新页面后中间件判定用户未登录,触发重定向。
内容的提问来源于stack exchange,提问作者Bright
相关产品推荐
相关产品推荐

