mongoose如何处理密码编码很好?

我想重构我的用户架构。 这个决定的主要原因是我不想担心密码和盐的产生。 所以我想将编码逻辑从pre save处理程序移到setter。 不幸的是我没有从setter访问对象的其他属性(如盐)。

所以默认的盐不起作用,用盐编码密码也不行。

我目前的实施是:

var userSchema = new mongoose.Schema({ username: { type: String, index: { unique: true, sparse: true }, required: true, lowercase: true, trim: true }, email: { type: String, index: { unique: true, sparse: true }, required: true, lowercase: true, trim: true }, salt: { type: String, select: false }, password: { type: String, select: false }, plainPassword: { type: String, select: false } }); // FIXME: password encoding only on change, not always userSchema.pre('save', function(next) { // check if a plainPassword was set if (this.plainPassword !== '') { // generate salt crypto.randomBytes(64, function(err, buf) { if (err) return next(err); this.salt = buf.toString('base64'); // encode password crypto.pbkdf2(this.plainPassword, this.salt, 25000, 512, function(err, encodedPassword) { if (err) return next(err); this.password = new Buffer(encodedPassword, 'binary').toString('base64'); this.plainPassword = ''; }.bind(this)); }.bind(this)); } next(); }); // statics userSchema.methods.hasEqualPassword = function(plainPassword, cb) { crypto.pbkdf2(plainPassword, this.salt, 25000, 512, function(err, encodedPassword) { if (err) return next(err); encodedPassword = new Buffer(encodedPassword, 'binary').toString('base64'); cb((this.password === encodedPassword)); }.bind(this)); } module.exports = mongoose.model('User', userSchema, 'Users'); 

有人设法将encryption移动到mongoosesetter?

问候,博多

您可以使用this关键字从setter中访问其他属性。 例如:

 userSchema.path('pass').set(function(v) { console.log(this); // Returns model instance return v; }); 

但是,setter不适合你的用例。 正如你可能知道的,HMAC-SHA1是非常昂贵的,因此将被阻塞,除非asynchronous执行。 Mongoose setter需要函数返回一个值,并且没有办法将crypto.pbkdf2()的callback的结果路由到setter函数的返回值。 这是一个asynchronousJavaScript的限制,而不是Mongoose本身:你不能在一个同步函数中包装一个asynchronous调用,因为这会破坏asynchronous链的本质。

安装程序被广泛用于简单的string操作和数据清理。

以下是仅使用实例方法进行encryption的演示:

 // Model method userSchema.methods.hashPassword = function(pass, callback) { // Generate salt (this should probably be async too) var salt = this.salt = crypto.createHash('md5').update(Math.random().toString()).digest('hex'); // Salt and Hash password crypto.pbkdf2(pass, salt, 25000, 512, callback); }); // Implementation var user = new User({ email: req.body.email }); user.hashPassword(req.body.pass, function(err, hash){ user.pass = hash; user.save(); });