我想在生成forgetpassword_token
24小时后,在mongodb文件中将null
更新为forgetpassword_token
。所以我使用Mongoose架构中间件和setTimeout
,但setTimeout
不工作。
我试图实现async await,这也不符合我的结果。
CompanySchema.post('updateOne',true, function(doc,next){
next();
setTimeout(this.update({},{ $set: { forgetpassword_token: null } }).then(result=>{
console.log(result);
}),10000000000);
});
这里的主要问题是这个实现是有缺陷的,因为如果你的节点应用程序在24小时窗口期间重新启动,你的超时将消失(是一个内存对象,而不是持久化),令牌将保持活动状态,让你暴露在安全性之下风险。
一个非常常见的解决方案是将token_expiration_date
与令牌一起保存,在相关密码重置请求期间进行日期比较。如果token_expiration_date
过期,请求将返回错误,服务器必须删除db上的令牌。
您也可以反过来:将token_creation_date
和max-token-ttl
存储在您的应用代码中(例如24小时)。在任何情况下,您都可以在请求时进行日期比较。
@NikKyriakides建议(参见评论)这种方法的更复杂的版本:你创建一个JWT的单个contains itself the expiration date令牌。当用户请求重置密码页面时,如果令牌有效,则只需要verify调用单个方法(无手动日期比较)。
更优雅和有效的解决方案是为您的forgetpassword_token创建不同的mongoose模式,并使用本机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评论,了解此解决方案的潜在缺点。