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

NextJS删除数据库中currentUser后仍登录,如何清除session或Cookie?

在Next.js中删除数据库用户后清除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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:32:49