SetTimeout 在 Mongoose 模式 post 中间件中不起作用
SetTimeout is not working in Mongoose schema post middleware
我正在尝试在生成 forgetpassword_token
24 小时后将 mongodb 文档中的 forgetpassword_token
更新为 null
。所以我正在使用 Mongoose 模式中间件和 setTimeout
,但是 setTimeout
不工作。
我已经尝试实现异步等待,但根据我的结果也无法正常工作。
CompanySchema.post('updateOne',true, function(doc,next){
next();
setTimeout(this.update({},{ $set: { forgetpassword_token: null } }).then(result=>{
console.log(result);
}),10000000000);
});
这里的主要问题是这个实现是有缺陷的,因为如果你的节点应用程序在 24 小时 window 期间重新启动,你的超时将 消失 (是内存中的对象,未持久化)并且令牌将保持活动状态,使您面临安全风险。
手动令牌验证
一个非常常见的解决方案是将 token_expiration_date
与令牌一起保存,在相关密码重置请求期间进行日期比较。如果 token_expiration_date
过期,请求 return 出错,服务器必须删除数据库上的令牌。
您也可以相反:将 token_creation_date
和 max-token-ttl
存储在您的应用程序代码中(例如 24 小时)。在任何情况下,您都会在请求时进行日期比较。
@NikKyriakides 建议(参见评论)此方法的更复杂版本:如果令牌有效调用单个方法(无手动日期比较),则创建单个 JWT token that contains itself the expiration date. When the user request the reset password page you need only to verify。
Mongo 过期选项
一个更优雅和有效的解决方案是为您的 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, so please also check them alongside with the related mongoose documentation 上存在很多问题。
作业调度程序
另一种方法是使用像 agenda 这样的作业调度程序来每小时检查过期的令牌并删除它们。是的,您可以将基于 setTimeout
的检查编写为应用程序的模块,但如果合适的工具已经存在,为什么不使用它呢?另请查看下面的@NikKyriakides 评论,了解此解决方案的潜在缺点。
我正在尝试在生成 forgetpassword_token
24 小时后将 mongodb 文档中的 forgetpassword_token
更新为 null
。所以我正在使用 Mongoose 模式中间件和 setTimeout
,但是 setTimeout
不工作。
我已经尝试实现异步等待,但根据我的结果也无法正常工作。
CompanySchema.post('updateOne',true, function(doc,next){
next();
setTimeout(this.update({},{ $set: { forgetpassword_token: null } }).then(result=>{
console.log(result);
}),10000000000);
});
这里的主要问题是这个实现是有缺陷的,因为如果你的节点应用程序在 24 小时 window 期间重新启动,你的超时将 消失 (是内存中的对象,未持久化)并且令牌将保持活动状态,使您面临安全风险。
手动令牌验证
一个非常常见的解决方案是将 token_expiration_date
与令牌一起保存,在相关密码重置请求期间进行日期比较。如果 token_expiration_date
过期,请求 return 出错,服务器必须删除数据库上的令牌。
您也可以相反:将 token_creation_date
和 max-token-ttl
存储在您的应用程序代码中(例如 24 小时)。在任何情况下,您都会在请求时进行日期比较。
@NikKyriakides 建议(参见评论)此方法的更复杂版本:如果令牌有效调用单个方法(无手动日期比较),则创建单个 JWT token that contains itself the expiration date. When the user request the reset password page you need only to verify。
Mongo 过期选项
一个更优雅和有效的解决方案是为您的 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, so please also check them alongside with the related mongoose documentation 上存在很多问题。
作业调度程序
另一种方法是使用像 agenda 这样的作业调度程序来每小时检查过期的令牌并删除它们。是的,您可以将基于 setTimeout
的检查编写为应用程序的模块,但如果合适的工具已经存在,为什么不使用它呢?另请查看下面的@NikKyriakides 评论,了解此解决方案的潜在缺点。