如何在 Sequelize 中的 setterMethod 之前运行模型验证?
Posted
技术标签:
【中文标题】如何在 Sequelize 中的 setterMethod 之前运行模型验证?【英文标题】:How can I run model validations before the setterMethod in Sequelize? 【发布时间】:2015-11-16 22:14:24 【问题描述】:我想保存一个散列密码。我为此使用了 setterMethod:
module.exports = (sequelize, DataTypes) ->
sequelize.define 'User',
# other model fields [...]
password:
type: DataTypes.STRING
validate: notEmpty: msg: 'You need to set a password.'
set: (pw) ->
salt = bcrypt.genSaltSync(10)
hash = bcrypt.hashSync(pw, salt)
@setDataValue('password', hash)
setter 首先运行。一个空字符串密码 (''
) 被散列成一个非空密码 (比如$2a$10$pDDIGnV.r47i9YOv0Fls/euQ0yYvfyq8T1SyP9VRQsTUAqptNmxXO
)。
验证器验证时,密码不再为空。
如何在 setter 之前验证密码?
我查看了hooks,但他们也没有提到二传手。
我正在使用sequelize@2.1.3
。
【问题讨论】:
【参考方案1】:我通过使用两个字段解决了这个问题,一个是处理输入和验证的VIRTUAL
,另一个是保存哈希密码的STRING
。
这个例子不是coffeescript
,但你应该可以轻松翻译。
password_hash:
type: DatabaseTypes.STRING,
allowNull: false,
validate:
notEmpty: true,
,
,
password:
type: DatabaseTypes.VIRTUAL,
allowNull: false,
// note that arrow functions cannot access "this", so use the form:
set: function setPassword(val)
// trigger validation on "password" field
this.setDataValue('password', val);
// hash the password, this can be done in one step by passing the
// number of salt rounds instead of the salt string.
this.setDataValue('password_hash', bcrypt.hashSync(val, 10));
,
validate:
notEmpty:
message: 'You need to set a password.',
,
,
,
当您对用户进行身份验证时,将输入的密码与User.password_hash
进行比较,而不是User.password
。
instanceMethods:
// authenticate user given a password
authenticate(password)
return bcrypt.compareSync(password, this.password_hash);
,
,
然后您可以调用此实例方法来验证User
。
User.findById(userId)
.then((user) =>
if (user.authenticate(password))
console.log('Authenticated');
else
console.log('Not authenticated');
);
【讨论】:
【参考方案2】:您可以使用 here 所述的 beforeCreate 挂钩来完成此操作
基本上,您的模型代码看起来像这样
User.init(
password:
type: DataTypes.TEXT,
allowNull: false,
validate:
len:
args: [6],
msg: "Minimum password length is 6 characters",
,
notEmpty:
args: [true],
msg: "Please enter a password",
,
notNull:
args: [true],
msg: "Please enter a password",
,
,
,
,
hooks:
beforeCreate: async (user) =>
(user.password = await bcrypt.hash(user.password, 10)),
,
sequelize,
modelName: "User",
,
);
查看 Sequelize hooks API 参考 here
【讨论】:
【参考方案3】:所以我使用了 beforeSave 钩子,用于插入和更新。我对其进行了测试似乎可以解决问题 - 验证也可以按预期工作。
User.init(
// attributes
email:
type: Sequelize.STRING,
allowNull: false,
unique: true,
validate:
isEmail:
msg: "Email address is entered is invalid",
,
,
,
password:
type: Sequelize.STRING,
allowNull: false,
validate:
notEmpty:
msg: "Password cannot be empty",
,
notNull:
msg: "Password cannot be null",
,
,
,
,
hooks:
beforeSave: (user, options) =>
if (options.fields.includes("password"))
user.password = bcrypt.hashSync(user.password, 10)
,
,
sequelize,
modelName: "user",
underscored: true,
)
【讨论】:
以上是关于如何在 Sequelize 中的 setterMethod 之前运行模型验证?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 sequelize 基于 sqlite3 中的“日期”列进行查询?
如何使用node.js控制sequelize中的内连接查询?