Sequelize实例方法不起作用
Sequelize instance methods not working
我正在尝试使用 Sequelize 的实例方法在尝试登录时验证密码。
我已将用户模型定义为:
var User = sequelize.define('User',{
id:{
type:DataTypes.BIGINT,
autoIncrement: true,
allowNull: false,
primaryKey:true
},
username:{
type:DataTypes.STRING,
unique:true
},
password:{
type: DataTypes.STRING
},
...
},
{
classMethods:{
associate:function(models){
...
}
}
},
{
instanceMethods:{
validatePassword:function(password){
return bcrypt.compareSync(password, this.password);
}
}
}
);
return User;
}
在我的登录路径中,我执行以下操作:
- 1) 从请求正文中检索用户名和密码
- 2) 检查数据库中是否存在用户名
- 3) 如果用户存在,获取用户对象并使用 validatePassword 方法将发送的密码与数据库中的散列密码进行比较。
这里是相关代码
var username = req.body.username || "";
var password = req.body.password || "";
models.User.findOne({ where: {username: username} }).
then(
function(user) {
if(user){
console.log(user.validatePassword(password));
}
....
每次我尝试登录时都会收到以下错误
[TypeError: user.validatePassword is not a function]
我做错了什么?
我认为您使用的 sequelize 模型定义不正确 api。
http://docs.sequelizejs.com/en/latest/docs/models-definition/#expansion-of-models
正确的做法是:
var User = sequelize.define('User',{}, {
classMethods: {
method1: ...
},
instanceMethods: {
method2: ...
}
});
不是这样的:
var User = sequelize.define('User',{}, {
classMethods: {
method1: ...
}
},{
instanceMethods: {
method2: ...
}
});
我们可以将 instanceLevelMethods 添加到原型中,
User.prototype.your-instance-level-method-name = function() {
return 'foo';
};
我是这样做的:
// Adding an instance level methods.
User.prototype.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
对于遇到类似问题的任何人,我 运行 遇到了同样的问题,但使用的是 Sequelize 5.21.5。根据这篇文章,Sequelize Instance Methods,从 Sequelize 4.0 及更高版本开始,您必须使用原型方法来定义实例方法,如下所示:
// Adding an instance level methods.
User.prototype.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
作为 sequelize "sequelize":“^5.21.7”访问实例方法,如@user1695032 return未定义。
这是我在 console.log() 传递用户对象 return 中未定义几个小时后发现的,来自以下查询:
User {
dataValues: {
id: 1,
firtName: null,
lasteName: null,
email: 'ugbanawaji.ekenekiso@ust.edu.ng',
phone: null,
password: 'b$yEWnBFMAe15RLLgyU3XlrOUyw19c4PCmh8GJe9QVz3YkbdzK5fHWu',
createdAt: 2020-05-27T21:45:02.000Z,
updatedAt: 2020-05-27T21:45:02.000Z
},
_previousDataValues: {
id: 1,
firtName: null,
lasteName: null,
email: 'ugbanawaji.ekenekiso@ust.edu.ng',
phone: null,
password: 'b$yEWnBFMAe15RLLgyU3XlrOUyw19c4PCmh8GJe9QVz3YkbdzK5fHWu',
createdAt: 2020-05-27T21:45:02.000Z,
updatedAt: 2020-05-27T21:45:02.000Z
},
_changed: {},
**_modelOptions: {**
timestamps: true,
validate: {},
freezeTableName: false,
underscored: false,
paranoid: false,
rejectOnEmpty: false,
whereCollection: { email: 'ugbanawaji.ekenekiso@ust.edu.ng' },
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [],
name: { plural: 'Users', singular: 'User' },
omitNull: false,
**instanceMethods: { comparePasswords: [Function: comparePasswords] },**
hooks: { beforeValidate: [Array] },
sequelize: Sequelize {
options: [Object],
config: [Object],
dialect: [MysqlDialect],
queryInterface: [QueryInterface],
models: [Object],
modelManager: [ModelManager],
connectionManager: [ConnectionManager],
importCache: [Object]
}
},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [
'id', 'firtName',
'lasteName', 'email',
'phone', 'password',
'createdAt', 'updatedAt'
]
},
isNewRecord: false
}
错误前的代码:
models.User.findOne({where: {email: req.body.email}}).then((user)=>{
console.log(user)
if(!user) {
res.status(401).json({ message: 'Authentication failed!' });
} else {
user.comparePasswords(req.body.password, (error, isMatch) =>{
console.log(error + ' -- ' + isMatch)
if(isMatch && !error) {
const token = jwt.sign(
{ username: user.username },
keys.secret,
{ expiresIn: '30h' }
);
res.status(200).json({ success: true,message: 'signed in successfully', token: 'JWT ' + token });
} else {
res.status(401).json({ success: false, message: 'Login failed!' });
}
});
}
}).catch((error)=>{
console.log(error)
res.status(500).json({ success: false, message: 'There was an error!'});
})
这个原因 TypeError: user.comparePasswords 不是函数
更改此行后:
** user.comparePasswords(req.body.password, (error, isMatch) =>{} **
对此:
** user._modelOptions.instanceMethods.comparePasswords(req.body.password, (error, isMatch) =>{}**
呜呜呜!一切正常
我使用这种方法:
const bcrypt = require('bcrypt-nodejs');
const constants = require('../constants/users');
module.exports = (Sequelize, type) => {
const User = Sequelize.define(constants.TABLE_NAME, {
username: {
type: type.STRING,
unique: true,
allowNull: false,
},
password: {
type: type.STRING,
allowNull: false,
},
// bla bla
});
const setSaltAndPassword = async function(user) {
if (user.changed('password')) {
const salt = bcrypt.genSaltSync(constants.PASSWORD_SALT_SIZE);
user.password = bcrypt.hashSync(user.password, salt);
}
};
User.prototype.validPassword = async function(password) {
return await bcrypt.compare(password, this.password);
};
User.beforeCreate(setSaltAndPassword);
User.beforeUpdate(setSaltAndPassword);
return User;
};
我正在尝试使用 Sequelize 的实例方法在尝试登录时验证密码。 我已将用户模型定义为:
var User = sequelize.define('User',{
id:{
type:DataTypes.BIGINT,
autoIncrement: true,
allowNull: false,
primaryKey:true
},
username:{
type:DataTypes.STRING,
unique:true
},
password:{
type: DataTypes.STRING
},
...
},
{
classMethods:{
associate:function(models){
...
}
}
},
{
instanceMethods:{
validatePassword:function(password){
return bcrypt.compareSync(password, this.password);
}
}
}
);
return User;
}
在我的登录路径中,我执行以下操作:
- 1) 从请求正文中检索用户名和密码
- 2) 检查数据库中是否存在用户名
- 3) 如果用户存在,获取用户对象并使用 validatePassword 方法将发送的密码与数据库中的散列密码进行比较。
这里是相关代码
var username = req.body.username || "";
var password = req.body.password || "";
models.User.findOne({ where: {username: username} }).
then(
function(user) {
if(user){
console.log(user.validatePassword(password));
}
....
每次我尝试登录时都会收到以下错误
[TypeError: user.validatePassword is not a function]
我做错了什么?
我认为您使用的 sequelize 模型定义不正确 api。 http://docs.sequelizejs.com/en/latest/docs/models-definition/#expansion-of-models
正确的做法是:
var User = sequelize.define('User',{}, {
classMethods: {
method1: ...
},
instanceMethods: {
method2: ...
}
});
不是这样的:
var User = sequelize.define('User',{}, {
classMethods: {
method1: ...
}
},{
instanceMethods: {
method2: ...
}
});
我们可以将 instanceLevelMethods 添加到原型中,
User.prototype.your-instance-level-method-name = function() {
return 'foo';
};
我是这样做的:
// Adding an instance level methods.
User.prototype.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
对于遇到类似问题的任何人,我 运行 遇到了同样的问题,但使用的是 Sequelize 5.21.5。根据这篇文章,Sequelize Instance Methods,从 Sequelize 4.0 及更高版本开始,您必须使用原型方法来定义实例方法,如下所示:
// Adding an instance level methods.
User.prototype.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
作为 sequelize "sequelize":“^5.21.7”访问实例方法,如@user1695032 return未定义。
这是我在 console.log() 传递用户对象 return 中未定义几个小时后发现的,来自以下查询:
User {
dataValues: {
id: 1,
firtName: null,
lasteName: null,
email: 'ugbanawaji.ekenekiso@ust.edu.ng',
phone: null,
password: 'b$yEWnBFMAe15RLLgyU3XlrOUyw19c4PCmh8GJe9QVz3YkbdzK5fHWu',
createdAt: 2020-05-27T21:45:02.000Z,
updatedAt: 2020-05-27T21:45:02.000Z
},
_previousDataValues: {
id: 1,
firtName: null,
lasteName: null,
email: 'ugbanawaji.ekenekiso@ust.edu.ng',
phone: null,
password: 'b$yEWnBFMAe15RLLgyU3XlrOUyw19c4PCmh8GJe9QVz3YkbdzK5fHWu',
createdAt: 2020-05-27T21:45:02.000Z,
updatedAt: 2020-05-27T21:45:02.000Z
},
_changed: {},
**_modelOptions: {**
timestamps: true,
validate: {},
freezeTableName: false,
underscored: false,
paranoid: false,
rejectOnEmpty: false,
whereCollection: { email: 'ugbanawaji.ekenekiso@ust.edu.ng' },
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [],
name: { plural: 'Users', singular: 'User' },
omitNull: false,
**instanceMethods: { comparePasswords: [Function: comparePasswords] },**
hooks: { beforeValidate: [Array] },
sequelize: Sequelize {
options: [Object],
config: [Object],
dialect: [MysqlDialect],
queryInterface: [QueryInterface],
models: [Object],
modelManager: [ModelManager],
connectionManager: [ConnectionManager],
importCache: [Object]
}
},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [
'id', 'firtName',
'lasteName', 'email',
'phone', 'password',
'createdAt', 'updatedAt'
]
},
isNewRecord: false
}
错误前的代码:
models.User.findOne({where: {email: req.body.email}}).then((user)=>{
console.log(user)
if(!user) {
res.status(401).json({ message: 'Authentication failed!' });
} else {
user.comparePasswords(req.body.password, (error, isMatch) =>{
console.log(error + ' -- ' + isMatch)
if(isMatch && !error) {
const token = jwt.sign(
{ username: user.username },
keys.secret,
{ expiresIn: '30h' }
);
res.status(200).json({ success: true,message: 'signed in successfully', token: 'JWT ' + token });
} else {
res.status(401).json({ success: false, message: 'Login failed!' });
}
});
}
}).catch((error)=>{
console.log(error)
res.status(500).json({ success: false, message: 'There was an error!'});
})
这个原因 TypeError: user.comparePasswords 不是函数
更改此行后:
** user.comparePasswords(req.body.password, (error, isMatch) =>{} **
对此:
** user._modelOptions.instanceMethods.comparePasswords(req.body.password, (error, isMatch) =>{}**
呜呜呜!一切正常
我使用这种方法:
const bcrypt = require('bcrypt-nodejs');
const constants = require('../constants/users');
module.exports = (Sequelize, type) => {
const User = Sequelize.define(constants.TABLE_NAME, {
username: {
type: type.STRING,
unique: true,
allowNull: false,
},
password: {
type: type.STRING,
allowNull: false,
},
// bla bla
});
const setSaltAndPassword = async function(user) {
if (user.changed('password')) {
const salt = bcrypt.genSaltSync(constants.PASSWORD_SALT_SIZE);
user.password = bcrypt.hashSync(user.password, salt);
}
};
User.prototype.validPassword = async function(password) {
return await bcrypt.compare(password, this.password);
};
User.beforeCreate(setSaltAndPassword);
User.beforeUpdate(setSaltAndPassword);
return User;
};