node.js 将 BCrypt 与 Sequelize 模型结合使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34120548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using BCrypt with Sequelize Model
提问by cphill
I'm trying to use the bcrypt-nodejspackage with my sequelize model and was tring to follow a tutorial to incorporate the hashing into my model, but I'm getting an error at generateHash. I can't seem to figure out the issue. Is there a better way to incorporate bcrypt?
我正在尝试将该bcrypt-nodejs包与我的续集模型一起使用,并试图按照教程将散列合并到我的模型中,但是我在generateHash. 我似乎无法弄清楚这个问题。有没有更好的方法来合并 bcrypt?
Error:
错误:
/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)
model:
模型:
var bcrypt = require("bcrypt-nodejs");
module.exports = function(sequelize, DataTypes) {
var 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
});
User.methods.generateHash = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};
User.methods.validPassword = function(password) {
return bcrypt.compareSync(password, this.local.password);
};
return User;
}
回答by Louay Alakkad
Methods should beprovided in the "options" argument of sequelize.define
方法应在“选项”参数中提供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;
}
回答by alditis
Other alternative:Use hook and bcrypt async mode
其他选择:使用 hook 和 bcrypt 异步模式
User.beforeCreate((user, options) => {
return bcrypt.hash(user.password, 10)
.then(hash => {
user.password = hash;
})
.catch(err => {
throw new Error();
});
});
回答by user1274820
There's a tutorial out thereon how to get a sequelize/postgreSQL auth system working with hooks and bcrypt.
有一个关于如何使用钩子和 bcrypt 获得 sequelize/postgreSQL 身份验证系统的教程。
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):
较新版本的 Sequelize 不喜欢以这种方式声明实例方法 - 许多人已经解释了如何解决这个问题(包括在原始教程中发布的人):
The original comment stillused 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 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);
}
On the node.js app in the login route where you check the password, there's a findOne section:
在您检查密码的登录路径中的 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');
}
});
All you have to do here is add the words asyncand awaitas well:
所有您需要做的,是添加的话async,并await还有:
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');
}
});

