Обратный вызов метода схемы Mongoose не работает

Я новичок в mongoose и node.js. Я стараюсь следовать этому руководству: https://scotch.io/tutorials/using-mongoosejs-in-node-js-and-mongodb-applications#sample-model-for-users

В моей точке входа index.js я попытался вызвать "chenya.saltHashPassword (function (err, passwordHash)". На самом деле он вызывается в user.js, потому что user.js может распечатать три сообщения журнала; однако журнала нет сообщение для вызова этого метода вообще в index.js. В отличие от этого метод save может распечатать сообщение журнала, указывающее на успешное сохранение:

//Lets load the mongoose module in our program
var mongoose = require('mongoose');

//Lets connect to our database using the DB server URL.
mongoose.connect('mongodb://localhost:27017/server_naturis');

// if our user.js file is at app/models/user.js
var User = require('./user');

// create a new user called Chenya
var chenya = new User({
  userName: 'Chenya',
  email: '[email protected]',
  password: 'Chenya'
});

// call the custom method. hash the password
chenya.saltHashPassword(function(err, passwordHash) { // NOT CALLED!
  if (err) {
    console.log('chenya.saltHashPassword: ' + err);
  } else {
    this.password = passwordHash;
    console.log('Your hashed password is ' + passwordHash);
  }
});

// call the built-in save method to save to the database
chenya.save(function(err) { // CALLED!
  if (err) {
    console.log('chenya.save: ' + err);
  } else {
    console.log('User saved successfully!');
  }
});

В моем user.js у меня есть функция схемы "userSchema.methods.saltHashPassword":

// grab the things we need
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// Require the crypto module for password hash
'use strict';
var crypto = require('crypto');

// create a schema
var userSchema = new Schema({
  userName: { type: String, required: true, unique: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
});

// add a schema method
/**
 * generates random string of characters i.e salt
 * @function
 * @param {number} length - Length of the random string.
 */
var genRandomString = function(length){
    return crypto.randomBytes(Math.ceil(length/2))
            .toString('hex') /** convert to hexadecimal format */
            .slice(0,length);   /** return required number of characters */
};
/**
 * hash password with sha512.
 * @function
 * @param {string} password - List of required fields.
 * @param {string} salt - Data to be validated.
 */
var sha512 = function(password, salt){
    var hash = crypto.createHmac('sha512', salt); /** Hashing algorithm sha512 */
    hash.update(password);
    var value = hash.digest('hex');
    return {
        salt:salt,
        passwordHash:value
    };
};
/**
 * a function that will use the above function 
 * to generate the hash that should be stored 
 * in the database as user’s password.
 */
userSchema.methods.saltHashPassword = function() {
    var salt = genRandomString(16); /** Gives us salt of length 16 */
    var passwordData = sha512(this.password, salt);
    console.log('UserPassword = '+ this.password);
    console.log('Passwordhash = '+ passwordData.passwordHash);
    console.log('\nSalt = '+ passwordData.salt);
    return passwordData.passwordHash;
}

// the schema is useless so far
// we need to create a model using it
var User = mongoose.model('User', userSchema);

// make this available to our users in our Node applications
module.exports = User;

Терминал:

UserPassword = Chenya
Passwordhash = 5bb5bf2181e2c713bae1eb49d1f3646b23db839368d38c33951774c92cec39a3c4b855aea30875e72cce6f271bdbdb27de8976c9316df09d086435b6c5629548

Salt = a88384d072b720de
(node:11717) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
User saved successfully!

person Chenya Zhang    schedule 20.08.2016    source источник


Ответы (1)


Вы не передаете параметр обратного вызова в userSchema.methods.saltHashPassword, но обрабатываете функцию так, как если бы вы это сделали.

Измените userSchema.methods.saltHashPassword на:

userSchema.methods.saltHashPassword = function(callback) { // <-- Add callback param
    var salt = genRandomString(16); /** Gives us salt of length 16 */
    var passwordData = sha512(this.password, salt);
    console.log('UserPassword = '+ this.password);
    console.log('Passwordhash = '+ passwordData.passwordHash);
    console.log('\nSalt = '+ passwordData.salt);

    // Your function that you passed in is called here
    callback(null, passwordData.passwordHash);
}

Причина, по которой ваш обратный вызов не был вызван в saltHashPassword, но был вызван в save, заключается в том, что Mongoose определяет этот метод, чтобы он требовал функции обратного вызова, которая принимает параметр для ошибки и фактическое возвращаемое значение.

При возникновении ошибки ожидается, что для обратного вызова будет определена обработка ошибок, что является хорошей практикой и почему вы видите учебные пособия, предлагающие сделать то же самое. Когда вы определяете свой собственный метод для Schema, у вас его больше нет, и вам придется настраивать его самостоятельно.

Как вы можете видеть в приведенной выше функции, вот что произошло. Теперь обратный вызов передается в качестве параметра, вызывающего его с помощью callback(null, passwordData.passwordHash), и он будет выполнен. Если у вас когда-либо возникала ошибка, вы можете сохранить ее как переменную, например err и передайте это в свою функцию как callback(err, null)

Возвращаясь к солям. Я не читал ваше руководство, но важно, чтобы вы сохранили их в базе данных вместе со своими пользовательскими данными, чтобы можно было проверить пароли при входе пользователя в систему.

Хороший ресурс здесь:

Хеширование пароля добавить соль + перец или достаточно соли? < / а>

Вам понадобится соль, чтобы сгенерировать тот же хешированный пароль, который вы храните в базе данных. Если у вас нет доступа к этой соли, вы не можете знать, сгенерирует ли введенный вами пароль тот же хеш.

person Mike    schedule 20.08.2016