我试图在生成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);
});
答案 0 :(得分:2)
这里的主要问题是此实现存在缺陷,因为如果在24小时窗口内重新启动节点应用程序,则超时将消失(是内存中对象,不会持久),并且该令牌将保持活动状态,使您面临安全风险。
一个非常常见的解决方案是将token_expiration_date
与令牌一起保存,并在相关密码重置请求期间进行日期比较。如果token_expiration_date
过期,则请求返回错误,服务器必须删除数据库上的令牌。
您也可以相反:将token_creation_date
和max-token-ttl
存储在您的应用代码中(例如24小时)。无论如何,您都可以在请求时间进行日期比较。
@NikKyriakides建议(请参阅评论)此方法的更复杂的版本:您创建一个JWT的单个contains itself the expiration date令牌。当用户请求重置密码页面时,如果令牌有效,则只需要verify即可调用单个方法(无需手动进行日期比较)。
一种更优雅,更有效的解决方案是为您的忘记密码令牌创建不同的猫鼬模式,并使用本地的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评论,以了解此解决方案的潜在缺点。