14

私は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
});

これまでのところ、私の検証はすべてスキーマで行われていますが、パスワード検証でこれを達成する方法を考えています。ユーザーが 2 つのフィールドにパスワードを入力すると、モデルはそれらが互いに同じであることを確認する必要があります。

この種の検証はスキーマに属していますか? 私はこの種の検証に慣れていません。

パスワードを検証するにはどうすればよいですか?

4

7 に答える 7

25

私は最終的に、この要点に示されているように、パスワードを照合するのとまったく同じ目的で、仮想パスと関数の組み合わせを使用してこれを実現できることを発見しました: https ://gist.github.com/1350041invalidate

直接引用するには:

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);
于 2012-12-23T22:50:32.833 に答える
12

パスワードの一致はクライアントインターフェイスに属し、サーバーに到達することはないと思います(DBレイヤーはすでに多すぎます)。2つの文字列が異なることをユーザーに伝えるためだけに、サーバーのラウンドトリップを行わない方が、ユーザーエクスペリエンスにとっては優れています。

シンコントローラー、ファットモデルに関しては...そこにあるこれらすべての銀の弾丸はオリジネーターに撃ち返されるはずです。どのような状況でも良い解決策はありません。それらのすべてを自分の文脈で考えてください。

ここにファットモデルのアイデアを取り入れることで、まったく異なる目的(パスワードマッチング)で機能(スキーマ検証)を使用できるようになり、現在使用している技術にアプリを依存させることができます。ある日、技術を変更したいと思うでしょう、そしてあなたはスキーマ検証なしで何かに到達するでしょう...そしてあなたはあなたのアプリの機能の一部がそれに依存していたことを覚えていなければなりません。そして、それをクライアント側またはコントローラーに戻す必要があります。

于 2012-12-21T15:19:36.033 に答える
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
    }
});
于 2012-12-21T01:25:58.360 に答える
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
};
于 2012-12-21T00:00:28.537 に答える
1

登録時に 2 番目の確認パスワードを送信する必要はありません。おそらく、クライアント側で 2 つのフィールドが等しいことを検証することで回避できます。

于 2012-12-21T07:08:49.187 に答える