我的userSchema
看起来像这样:
var userSchema = new Schema({
name: {
type: String
, required: true
, validate: [validators.notEmpty, 'Name is empty']
}
, username: {
type: String
, required: true
, validate: [validators.notEmpty, 'Username is empty']
}
, email: {
type: String
, required: true
, validate: [
{ validator: validators.notEmpty, msg: 'Email is empty' }
, { validator: validators.isEmail, msg: 'Invalid email' }
]
}
, salt: String
, hash: String
});
到目前为止,我所有的验证都发生在模式中,我想知道如何通过密码验证来实现这一目标。用户将密码输入两个字段,模型应检查它们是否相同。
这种验证是否属于架构?我是这种验证的新手。
我应该如何验证密码?
答案 0 :(得分:23)
我最终发现您可以使用虚拟路径和invalidate
函数的组合来实现此功能,如此要点所示,其目的与匹配密码完全相同:{ {3}}
直接引用:
CustomerSchema.virtual('password')
.get(function() {
return this._password;
})
.set(function(value) {
this._password = value;
var salt = bcrypt.gen_salt_sync(12);
this.passwordHash = bcrypt.encrypt_sync(value, salt);
});
CustomerSchema.virtual('passwordConfirmation')
.get(function() {
return this._passwordConfirmation;
})
.set(function(value) {
this._passwordConfirmation = value;
});
CustomerSchema.path('passwordHash').validate(function(v) {
if (this._password || this._passwordConfirmation) {
if (!val.check(this._password).min(6)) {
this.invalidate('password', 'must be at least 6 characters.');
}
if (this._password !== this._passwordConfirmation) {
this.invalidate('passwordConfirmation', 'must match confirmation.');
}
}
if (this.isNew && !this._password) {
this.invalidate('password', 'required');
}
}, null);
答案 1 :(得分:10)
我认为密码匹配属于客户端界面,不应该到达服务器(DB层已经太多了)。对于用户体验而言,最好不要让服务器往返只是告诉用户2个字符串是不同的。
对于瘦控制器,胖子模型......那些所有这些银子弹都应该向原发者射击。在任何情况下都没有解决方案。在他们自己的背景下思考每个人。
在这里引入胖模型的想法,让你使用一个功能(模式验证)用于完全不同的目的(密码匹配),并使你的应用程序依赖于你现在使用的技术。有一天你会想要改变技术,你会得到一些没有模式验证的东西......然后你必须记住你的应用程序的部分功能依赖于它。而且你必须将它移回客户端或控制器。
答案 2 :(得分:2)
我在./routes/signup.js中的架构级别之前使用了express-validator:
exports.post = function(req, res){
req.assert('email', 'Enter email').notEmpty().isEmail();
req.assert('username', 'Enter username').notEmpty().isAlphanumeric().len(3,20);
req.assert('password', 'Enter password').notEmpty().notContains(' ').len(5,20);
res.locals.err = req.validationErrors(true);
if ( res.locals.err ) {
res.render('signup', { message: { error: 'Woops, looks like we need more info...'} });
return;
}
...//save
};
答案 3 :(得分:2)
您可以通过向Schema.methods
添加新的函数属性来将自定义方法附加到模型实例(您还可以使用Schema.statics
创建模式函数。)以下是验证用户密码的示例:
userSchema.methods.checkPassword = function(password) {
return (hash(password) === this.password);
};
// You could then check if a user's password is valid like so:
UserModel.findOne({ email: 'email@gmail.com' }, function(err, user) {
if (user.checkPassword('secretPassword')) {
// ... user is legit
}
});
答案 4 :(得分:2)
我知道线程已经老了但是如果可以节省某人的时间...... 我的方法使用预验证钩子,对我来说非常适合
openDatabase()
答案 5 :(得分:1)
无需提交第二个验证密码进行注册。 您可能可以通过验证客户端的两个字段是否相同来实现。
答案 6 :(得分:0)
有点晚了,但是为了人们遇到类似的问题。我最近遇到了类似的问题,这就是我的解决方法;我使用了一个名为joi的图书馆
const joi = require('joi');
...
function validateUser(user){
const schema = joi.object({
username: joi.string().min(3).max(50).required(),
email: joi.string().min(10).max(255).required().email(),
password: joi.string().min(5).max(255).required(),
password2: joi.string().valid(joi.ref('password')).required(),
});
return schema.validate(user);
}
exports.validate = validateUser;