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

如何在AuthJs(NextAuth)中实现登录后8小时自动删除未验证用户的触发逻辑

如何在AuthJs(NextAuth)中实现登录后8小时自动删除未验证用户的触发逻辑

嘿,我来帮你梳理下实现这个需求的具体步骤,结合你用的NextAuth、Mongoose和Next.js,咱们一步步来落地:


第一步:完善用户模型(补充关键字段)

你当前的User Schema缺少两个核心字段:邮箱验证状态和登录时间。NextAuth的MongoDB Adapter其实默认会生成emailVerified字段(验证后存时间,未验证则为null),咱们把它加到Schema里,再新增lastLoginAt字段记录用户登录时间,这样才能准确计算8小时的窗口期:

import { Schema, Model, Types, Document, model, models } from 'mongoose';

export interface Users extends Document {
    name: string
    email: string
    emailVerified: Date | null; // 新增:标记邮箱是否验证,未验证为null
    lastLoginAt: Date; // 新增:记录用户最后登录的时间点
}

const UserSchema = new Schema<Users>({
    name: {
        type: String,
        required: true
    },
    email: {
        type: String,
        required: true,
        unique: true // 建议加上,避免重复邮箱注册
    },
    emailVerified: {
        type: Date,
        default: null
    },
    lastLoginAt: {
        type: Date,
        required: true
    }
})

export default models.User || model<Users>('User', UserSchema)

第二步:在NextAuth中记录登录时间

因为你的计时是从用户登录后开始算的,所以要在signIn回调里更新用户的lastLoginAt字段,确保每次登录都刷新这个时间:

export const { auth, handlers, signIn, signOut } = NextAuth({
    adapter: MongoDBAdapter(client),
    session: { strategy: "jwt" },
    callbacks: {
        async session({ session, token, user }) {
            return {
                ...session,
                user: {
                    ...session.user,
                    emailVerified: user?.emailVerified, // 可选:把验证状态带到前端session里
                    lastLoginAt: user?.lastLoginAt
                },
            }
        },
        // 新增signIn回调,更新登录时间
        async signIn({ user, account, profile, email, credentials }) {
            // 登录成功后,更新当前用户的lastLoginAt为当前时间
            if (user.id) {
                await models.User.findByIdAndUpdate(
                    user.id,
                    { lastLoginAt: new Date() },
                    { new: true }
                );
            }
            return true; // 允许登录
        }
    },

    ...authConfig,
})

第三步:实现自动删除的触发逻辑

这里有两种靠谱的方案,推荐结合使用:

方案一:定时任务(核心推荐)

用node-cron包定期扫描数据库,自动删除符合条件的用户。这种方式最可靠,不管用户有没有后续操作,都会按时执行清理。

  1. 先安装依赖:
npm install node-cron
# 或 yarn add node-cron
  1. 在项目中创建清理脚本,比如scripts/cleanupUnverifiedUsers.ts:
import cron from 'node-cron';
import User from '@/models/User'; // 替换成你的User模型路径
import mongoose from 'mongoose';
import { connectDB } from '@/lib/db'; // 替换成你的数据库连接函数

// 定义清理逻辑
const cleanupUnverifiedUsers = async () => {
    try {
        await connectDB(); // 连接数据库
        const eightHoursAgo = new Date(Date.now() - 8 * 60 * 60 * 1000);

        // 删除未验证且登录超过8小时的用户
        const result = await User.deleteMany({
            emailVerified: null,
            lastLoginAt: { $lt: eightHoursAgo }
        });

        console.log(`成功清理 ${result.deletedCount} 个未验证超时用户`);
    } catch (error) {
        console.error('清理未验证用户出错:', error);
    } finally {
        await mongoose.connection.close(); // 关闭数据库连接
    }
};

// 设定定时规则:比如每小时执行一次(可根据需求调整频率)
cron.schedule('0 * * * *', () => {
    console.log('开始执行未验证用户清理任务...');
    cleanupUnverifiedUsers();
});

如果是部署在Vercel上,你可以直接用Vercel自带的Cron Jobs功能,在控制台配置定时任务,不用自己维护node-cron进程。

方案二:请求时检查(补充兜底)

除了定时任务,你可以在用户每次请求时(比如session回调里)检查当前用户是否符合删除条件,及时清理活跃的超时用户:

// 在session回调中添加检查逻辑
async session({ session, token, user }) {
    if (user?.emailVerified === null && user?.lastLoginAt) {
        const eightHoursAgo = new Date(Date.now() - 8 * 60 * 60 * 1000);
        // 如果用户未验证且登录超过8小时,直接删除并退出
        if (new Date(user.lastLoginAt) < eightHoursAgo) {
            await models.User.findByIdAndDelete(user.id);
            await signOut({ redirect: false });
            return null; // 返回空session,前端可处理跳转至登录页
        }
    }

    return {
        ...session,
        user: {
            ...session.user,
            emailVerified: user?.emailVerified,
            lastLoginAt: user?.lastLoginAt
        },
    }
},

注意事项

  • 测试时可以把时间缩短(比如1分钟),方便快速验证逻辑是否正常
  • 确保数据库连接函数能在定时任务中正常工作
  • 如果用Next.js App Router,定时脚本可以放在app/api/目录下作为API路由,或者在服务器启动时执行

备注:内容来源于stack exchange,提问作者Febry Aryo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:29:34