NextJS删除数据库中currentUser后仍登录,如何清除session或Cookie?
核心逻辑是每次请求时验证用户在数据库中的存在性,一旦发现用户已被删除,立即销毁会话并清除相关Cookie。下面分不同认证场景给出具体实现:
一、使用NextAuth.js的场景
如果你的项目用NextAuth做认证,主要通过回调函数和中间件实现:
1. 在Session/JWT回调中校验用户存在
修改[...nextauth].js中的回调逻辑,每次生成session或JWT时检查用户是否存在:
import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; import { prisma } from "@/lib/prisma"; // 你的数据库客户端 export const authOptions = { providers: [ CredentialsProvider({ // 你的登录逻辑... }), ], callbacks: { async session({ session }) { // 从数据库查询当前用户 const userExists = await prisma.user.findUnique({ where: { email: session.user.email }, }); // 如果用户不存在,返回空session触发登出 if (!userExists) { return null; } return session; }, async jwt({ token }) { const userExists = await prisma.user.findUnique({ where: { email: token.email }, }); if (!userExists) { return null; // 销毁JWT } return token; }, }, }; export default NextAuth(authOptions);
2. 用Middleware全局拦截请求
在middleware.js中拦截所有需要认证的路由,检查用户状态:
import { getToken } from "next-auth/jwt"; import { NextResponse } from "next/server"; import { prisma } from "@/lib/prisma"; export async function middleware(req) { const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET }); const path = req.nextUrl.pathname; // 跳过登录页等公开路由 if (path === "/login") { return NextResponse.next(); } // 如果有token但用户不存在,清除session并重定向到登录页 if (token) { const userExists = await prisma.user.findUnique({ where: { email: token.email }, }); if (!userExists) { // 清除NextAuth的session cookie const response = NextResponse.redirect(new URL("/login", req.url)); response.cookies.set("next-auth.session-token", "", { expires: new Date(0) }); response.cookies.set("next-auth.csrf-token", "", { expires: new Date(0) }); return response; } } // 其他正常逻辑... } export const config = { matcher: ["/dashboard/:path*", "/profile/:path*"], // 需要保护的路由 };
二、自定义认证(自己管理Session/Cookie)
如果是自己实现的认证逻辑,需要在服务器端和前端双重校验:
1. 服务器端API/路由处理
在受保护的API路由或服务器组件中,先从Cookie读取sessionId,再查数据库验证用户:
// app/api/protected/route.js import { cookies } from "next/headers"; import { prisma } from "@/lib/prisma"; export async function GET(req) { const sessionId = cookies().get("sessionId")?.value; if (!sessionId) { return new Response("Unauthorized", { status: 401 }); } // 查询session关联的用户 const session = await prisma.session.findUnique({ where: { id: sessionId }, include: { user: true }, }); if (!session || !session.user) { // 清除session cookie const response = new Response("User not found", { status: 401 }); response.cookies.set("sessionId", "", { expires: new Date(0), path: "/" }); return response; } // 正常返回数据... }
2. 前端页面校验
在客户端组件中,页面加载时调用API检查用户状态,发现用户不存在则手动清除Cookie并跳转:
// app/profile/page.jsx "use client"; import { useEffect } from "react"; import { useRouter } from "next/navigation"; export default function Profile() { const router = useRouter(); useEffect(() => { const checkUserExists = async () => { try { const res = await fetch("/api/protected"); if (res.status === 401) { // 清除自定义cookie document.cookie = "sessionId=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; router.push("/login"); } } catch (err) { console.error(err); } }; checkUserExists(); }, [router]); // 页面内容... }
三、关键注意事项
- 不要只依赖前端校验:必须在服务器端(中间件、API路由、服务器组件)做核心校验,前端校验只是提升用户体验。
- Cookie清除要彻底:清除时要指定
path=/,确保所有路由下的Cookie都被删除,同时设置过期时间为过去的时间。 - NextAuth的特殊处理:NextAuth的session cookie有固定名称(
next-auth.session-token、next-auth.csrf-token等),清除时要对应这些名称。
内容的提问来源于stack exchange,提问作者etrix
相关产品推荐
相关产品推荐

