使用Mongoose模式验证密码/确认密码

时间:2012-12-20 23:29:17

标签: node.js mongodb express mongoose

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

到目前为止,我所有的验证都发生在模式中,我想知道如何通过密码验证来实现这一目标。用户将密码输入两个字段,模型应检查它们是否相同。

这种验证是否属于架构?我是这种验证的新手。

我应该如何验证密码?

7 个答案:

答案 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;