无法散列密码并将其设置为在mongodb模式中的字段

我正在试用一个由madhusudhan srinivasa为node.js,express和mongodb的演示博客平台。 。 我根据他的实施创build了一个博客。 但是,我在哈希密码和创build用户方面遇到了麻烦。 我附加了创build用户的模型和控制器,因为我不知道问题出在哪里。

我的用户创build表单具有用bodyParser传递给控制器​​的用户名和密码字段。

我的问题是,当我提交表单来创build一个用户,我得到一个未定义的错误从哈希validation函数,“无法获得未定义的长度”。

如果我评论这个哈希validation函数,创build一个用户。 但是,当我在mongodb命令行中查看创build的用户时,它根本没有哈希字段,但名称和盐字段设置正确。 但是,当我console.log散列内encryptPassword(),它似乎输出一个正确的哈希密码。

我一直在研究这个问题几个小时,完全不知道问题是什么。

模型:

var mongoose = require('mongoose') , Schema = mongoose.Schema , crypto = require('crypto') , _ = require('underscore') // user schema var UserSchema = new Schema ({ name: { type: String, default: '' }, hash: { type: String, default: '' }, salt: { type: String, default: '' } }) UserSchema .virtual('password') .set(function(password) { this._password = password this.salt = this.makeSalt() this.hash = this.encryptPassword(password) }) .get(function() { return this._password }) var validatePresenceOf = function (value) { return value && value.length } UserSchema.path('name').validate(function(name) { return name.length }, 'you need a name..') UserSchema.path('name').validate(function(name, cb) { var User = mongoose.model('User') if (this.isNew || this.isModified('name')) { User.find({ name : name }).exec(function(err, users) { cb(!err && users.length === 0) }) } else cb(true) }, 'name already exists..') // i get an undefined error at the below function: UserSchema.path('hash').validate(function(hash) { return hash.length }, 'you need a password...') UserSchema.pre('save', function(next) { if (!this.isNew) return next() if (!validatePresenceOf(this.password)) { next(new Error('invalid password.')) } else { next() } }) UserSchema.methods = { // auth authenticate: function(plaintext) { return this.encryptPassword(plaintext) === this.hash }, // salt makeSalt: function() { return crypto.randomBytes(128) }, encryptPassword: function (password) { if (!password) return '' crypto.pbkdf2(password, this.salt, 2000, 128, function(err, derivedKey) { if (err) throw err var myhash = derivedKey.toString() console.log('hash: ' + myhash) return myhash }) } } mongoose.model('User', UserSchema) 

控制器:

 exports.create = function(req, res) { var user = new User(req.body) user.save(function (err) { if (err) { return res.render('signup', { errors: err.errors, user: user, title: 'SIGN UP' }) } req.logIn(user, function(err) { if (err) return next(err) return res.redirect('backend') }) }) } 

您的encryption过程使用crypto.pbkdf2 ,这是一个asynchronousfunction。 这意味着encryptPassword()在您的虚拟设置器被调用时不会返回你的哈希值。 你的哈希只会返回传递给crypto.pbkdf2的callback – 这就是为什么console.log在你的例子中的作品。

解决这个问题的一个方法是改变encryptPassword()来使用pbkdf2的同步同步 – crypto.pbkdf2Sync 。 链接到文档

下面的例子(有一些error handling):

 encryptPassword: function (password) { if (!password) return '' var encrypted try { encrypted = crypto.pbkdf2Sync(password, this.salt, 2000, 128).toString(); return encrypted } catch (err) { // Handle error } } 
  encryptPassword: function (password) { if (!password || !this.salt) return ''; var salt = new Buffer(this.salt, 'base64'); return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64'); }