Using BCrypt with Sequelize Model

前端 未结 3 1030
礼貌的吻别
礼貌的吻别 2020-12-05 10:47

I\'m trying to use the bcrypt-nodejs package with my sequelize model and was tring to follow a tutorial to incorporate the hashing into my model, but I\'m getti

相关标签:
3条回答
  • 2020-12-05 11:15

    Other alternative: Use hook and bcrypt async mode

    User.beforeCreate((user, options) => {
    
        return bcrypt.hash(user.password, 10)
            .then(hash => {
                user.password = hash;
            })
            .catch(err => { 
                throw new Error(); 
            });
    });
    
    0 讨论(0)
  • 2020-12-05 11:30

    Methods should be provided in the "options" argument of 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;
    }
    
    0 讨论(0)
  • 2020-12-05 11:37

    There's a tutorial out there on how to get a sequelize/postgreSQL auth system working with hooks and bcrypt.

    The guy who wrote the tutorial did not use async hash/salt methods; in the user creation/instance method section he used the following code:

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

    Newer versions of Sequelize don't like instance methods being declared this way - and multiple people have explained how to remedy this (including someone who posted on the original tutorial):

    The original comment still used the synchronous methods:

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

    All you need to do to make these functions asyncronous is this:

    Async beforeCreate bcrypt genSalt and genHash functions:

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

    On the node.js app in the login route where you check the password, there's a findOne section:

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

    All you have to do here is add the words async and await as well:

    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');
        }
    });
    
    0 讨论(0)
提交回复
热议问题