简体   繁体   English

无法哈希密码并将其设置为mongodb模式中的字段

[英]can't hash a password and set it to field in mongodb schema

I'm experimenting with a demo blog platform by madhusudhan srinivasa for node.js, express, and mongodb. 我正在尝试由madhusudhan srinivasa开发的演示博客平台,用于node.js,express和mongodb。 . I've created a blog heavily based on his implementation. 我主要根据他的实现创建了一个博客。 But, I'm having trouble with hashing a password and creating a user. 但是,我在散列密码和创建用户方面遇到麻烦。 I've attached the model and controller for creating a user since I don't know exactly where the problem is. 我已经附加了用于创建用户的模型和控制器,因为我不知道确切的问题出在哪里。

My user creation form has user and password fields which are passed into the controller with bodyParser. 我的用户创建表单具有用户和密码字段,这些字段通过bodyParser传递到控制器中。

My problem is that when i submit the form to create a user, I get an undefined error from the hash validation function, "cannot get length of undefined." 我的问题是,当我提交表单以创建用户时,我从哈希验证功能中收到未定义的错误,“无法获取未定义的长度”。

If i comment this hash validation function out, a user is created. 如果我将此哈希验证功能注释掉,则会创建一个用户。 But when i look at the created user in mongodb command line, it doesn't have a hash field at all, but the name and salt fields are set correctly. 但是,当我在mongodb命令行中查看创建的用户时,它根本没有哈希字段,但是名称和盐字段设置正确。 However, when I console.log the hash inside encryptPassword(), it seems to output a correctly hashed password. 但是,当我在console.log内cryptoPassword()中的哈希值时,似乎输出了正确哈希值的密码。

I have been working on this for hours and am completely at a loss to what the problem could be. 我已经为此工作了几个小时,完全不知道可能是什么问题。

model: 模型:

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)

controller: 控制器:

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')
        })
    })
}

Your encryption procedure uses crypto.pbkdf2 , which is an asynchronous function. 您的加密过程使用crypto.pbkdf2 ,这是一个异步函数。 This means encryptPassword() will not return your hash when your virtual setter is called. 这意味着在调用虚拟设置器时,encryptPassword()将不会返回您的哈希。 Your hash only gets returned inside of the callback passed to crypto.pbkdf2 - which is why console.log works in your example. 您的哈希只会在传递给crypto.pbkdf2的回调内部返回-这就是为什么console.log在您的示例中起作用的原因。

One way to solve this problem is to change encryptPassword() to make use of pbkdf2's synchronous sibling - crypto.pbkdf2Sync . 解决此问题的一种方法是更改​​cryptoPassword()以利用pbkdf2的同步兄弟crypto.pbkdf2Sync Link to docs 链接到文档

Example below (with some 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');
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM