简体   繁体   中英

this.password is undefined in comparePassword method when using Bcrypt with mongoose. How to solve?

After fetching records from Mongo DB, comparePassword method is called to compare the password entered by user and the password stored in database. On printing the record all the data is shown, while inside comparePassword this.password is coming as undefined.

    User.findOne ({ username : req.body.username },
      function(err, user) {
  if (err) throw err;
console.log(user);
 user.comparePassword(req.body.password, function(err, isMatch) {
    if (err) throw err;
    console.log('Password Match:', isMatch); 
});});

Method:

    UserCredentialSchema.methods.comparePassword = function(pwd, cb) {
bcrypt.compare(pwd, this.password, function(err, isMatch) {
    console.log(this.password);
    if (err) return cb(err);
    cb(null, isMatch);
});};

This is a bit old, but I bump into this same problem. After spending half day, I found out why and might be applicable.

My problem is caused by the password field being declared with select: false in the schema. See the code below

var personSchema = new Schema({
  first       :   {type: String, required: 'FirstNameInvalid'},
  last        :   String,
  email       :   {type: String, unique: true, lowercase: true, required: 'EmailInvalid'},
  password    :   {type: String, select: false, required: 'PasswordInvalid'},
  isLocked    :   Boolean,
  isAdmin     :   Boolean
});

By changing the password declaration to select: true , or even removing the whole select statement, the problem is fixed.

Note that there are some security risk involved by removing the select statement. However this will be beyond the discussion of this topic

you need to call the comparePassword with function.call(thisArg, arg1, arg2, ...) to bind the correct context of 'this'

so basicially instead of:

user.comparePassword(req.body.password, function(err, isMatch) {
    if (err) throw err;
    console.log('Password Match:', isMatch); 
});

use:

user.comparePassword.call(this, req.body.password, function(err, isMatch) {
    if (err) throw err;
    console.log('Password Match:', isMatch); 
});

Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

You should try compare compareSync() instead of compare() . Hope this will work for you.

    UserCredentialSchema.methods.comparePassword = function(pwd, cb) {
    var result = bcrypt.compareSync(pwd, this.password);
    if (result) {
           cb(null, result);
    } else {
           return cb(err);
    }
   };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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