使用BCrypt和Sequelize Model

时间:2015-12-06 17:42:37

标签: node.js sequelize.js bcrypt

我试图在我的续集模型中使用bcrypt-nodejs包,并且想要按照教程将哈希合并到我的模型中,但我在{{1}收到错误}}。我似乎无法弄清楚这个问题。是否有更好的方法来合并bcrypt?

错误:

generateHash

模型:

/Users/user/Desktop/Projects/node/app/app/models/user.js:26
User.methods.generateHash = function(password) {
                          ^
TypeError: Cannot set property 'generateHash' of undefined
    at module.exports (/Users/user/Desktop/Projects/node/app/app/models/user.js:26:27)
    at Sequelize.import (/Users/user/Desktop/Projects/node/app/node_modules/sequelize/lib/sequelize.js:641:30)

3 个答案:

答案 0 :(得分:14)

"选项"中提供的方法should be sequelize.define

的论点
const bcrypt = require("bcrypt");

module.exports = function(sequelize, DataTypes) {
    const User = sequelize.define('users', {
        annotation_id: {
            type: DataTypes.INTEGER,
            autoIncrement: true,
            primaryKey: true
        },
        firstName: {
            type: DataTypes.DATE,
            field: 'first_name'
        },
        lastName: {
            type: DataTypes.DATE,
            field: 'last_name'
        },
        email: DataTypes.STRING,
        password: DataTypes.STRING
    }, {
        freezeTableName: true,
        instanceMethods: {
            generateHash(password) {
                return bcrypt.hash(password, bcrypt.genSaltSync(8));
            },
            validPassword(password) {
                return bcrypt.compare(password, this.password);
            }
        }
    });

    return User;
}

答案 1 :(得分:10)

其他选择:使用hook和bcrypt异步模式

User.beforeCreate((user, options) => {

    return bcrypt.hash(user.password, 10)
        .then(hash => {
            user.password = hash;
        })
        .catch(err => { 
            throw new Error(); 
        });
});

答案 2 :(得分:4)

关于如何获得使用钩子和bcrypt的sequelize / postgreSQL身份验证系统的方法,a tutorial out there

编写本教程的人出于某种原因未使用异步哈希/盐方法(而且我看到的代码到处都没有真正的答案)。

无论如何,我花了数小时意识到我对Promise或异步javascript不太了解,我想我已经找到了处理方法。

异步方法实际上是如此的优雅和美丽,我觉得自己是个白痴,但是无论如何:

在用户创建/实例方法部分中,他使用了以下代码:

hooks: {
  beforeCreate: (user) => {
    const salt = bcrypt.genSaltSync();
    user.password = bcrypt.hashSync(user.password, salt);
  }
},
instanceMethods: {
  validPassword: function(password) {
    return bcrypt.compareSync(password, this.password);
  }
}    

较新版本的Sequelize不喜欢以这种方式声明实例方法-并且许多人已经解释了如何解决此问题(包括在原始教程中发布的人):

最初的评论 still 使用的同步方法有些令人沮丧。

User.prototype.validPassword = function (password) {
    return bcrypt.compareSync(password, this.password);
};

显然我是个白痴,因为您需要做的就是使这些功能异步:

在创建bcrypt genSalt和genHash函数之前进行异步:

beforeCreate: async function(user) {
    const salt = await bcrypt.genSalt(10); //whatever number you want
    user.password = await bcrypt.hash(user.password, salt);
}

User.prototype.validPassword = async function(password) {
    return await bcrypt.compare(password, this.password);
}

对于beforeCreate代码,这实际上没有任何改变-似乎可以正常工作。

在登录路径中用于检查密码的node.js应用上,有一个findOne部分:

User.findOne({ where: { username: username } }).then(function (user) {
    if (!user) {
        res.redirect('/login');
    } else if (!user.validPassword(password)) {
        res.redirect('/login');
    } else {
        req.session.user = user.dataValues;
        res.redirect('/dashboard');
    }
});

您在这里要做的就是同时添加单词asyncawait

User.findOne({ where: { username: username } }).then(async function (user) {
    if (!user) {
        res.redirect('/login');
    } else if (!await user.validPassword(password)) {
        res.redirect('/login');
    } else {
        req.session.user = user.dataValues;
        res.redirect('/dashboard');
    }
});

如果我在这里做错了事,请告诉我-非常感谢-希望这对在那里的人有所帮助。