SetTimeout在Mongoose模式发布中间件中不起作用

时间:2019-03-28 09:29:36

标签: node.js settimeout mongoose-schema

我试图在生成forgetpassword_token 24小时后将mongodb文档中的null更新为forgetpassword_token。因此,我正在使用Mongoose模式中间件和setTimeout,但是setTimeout无法正常工作。

我尝试实现异步等待,但根据我的结果,该等待也不起作用。

CompanySchema.post('updateOne',true, function(doc,next){
    next();
       setTimeout(this.update({},{ $set: { forgetpassword_token: null } }).then(result=>{
           console.log(result);
                   }),10000000000);
       });

1 个答案:

答案 0 :(得分:2)

这里的主要问题是此实现存在缺陷,因为如果在24小时窗口内重新启动节点应用程序,则超时将消失(是内存中对象,不会持久),并且该令牌将保持活动状态,使您面临安全风险。

手动令牌验证

一个非常常见的解决方案是将token_expiration_date与令牌一起保存,并在相关密码重置请求期间进行日期比较。如果token_expiration_date过期,则请求返回错误,服务器必须删除数据库上的令牌。

您也可以相反:将token_creation_datemax-token-ttl存储在您的应用代码中(例如24小时)。无论如何,您都可以在请求时间进行日期比较。

@NikKyriakides建议(请参阅评论)此方法的更复杂的版本:您创建一个JWT的单个contains itself the expiration date令牌。当用户请求重置密码页面时,如果令牌有效,则只需要verify即可调用单个方法(无需手动进行日期比较)。

Mongo到期选项

一种更优雅,更有效的解决方案是为您的忘记密码令牌创建不同的猫鼬模式,并使用本地的mongo / mongoose expire option在创建文档后的固定时间后自动删除它们。

const secondsInADay = 60 * 60 * 24;

const tokenSchema = mongoose.Schema({
    value: String
}, {timestamps: true});

tokenSchema.index({createdAt: 1},{expireAfterSeconds: secondsInADay});
const Token = mongoose.model('Token', tokenSchema);

然后将对这个架构的引用添加到您现有的CompanySchema中:

forgetpassword_token: {type: mongoose.Schema.Types.ObjectId, ref: 'Token'}

this topic上存在很多问题,因此也请与相关的mongoose documentation一起检查。

工作计划程序

另一种方法是使用作业调度程序(例如agenda)每小时检查一次过期的令牌并删除它们。是的,您可以编写基于setTimeout的支票作为您应用程序的模块,但是如果存在正确的工具,为什么不使用它呢?另外,请查看下面的@NikKyriakides评论,以了解此解决方案的潜在缺点。