1

ユーザースキーマをリファクタリングしたい。この決定の主な理由は、パスワードとソルトの生成について心配したくないということです。そこで、エンコードロジックを保存前ハンドラーからセッターに移動したいと思います。残念ながら、セッターからオブジェクトの他のプロパティ(saltなど)にアクセスできません。

したがって、saltのデフォルト設定は機能せず、saltを使用したパスワードのエンコードも機能しません。

私の現在の実装は次のとおりです。

var userSchema = new mongoose.Schema({

    username: { 
        type: String, 
        index: { unique: true, sparse: true }, 
        required: true, lowercase: true, trim: true
    },

    email: {
        type: String,
        index: { unique: true, sparse: true }, 
        required: true, lowercase: true, trim: true
    },

    salt: {
        type: String,
        select: false
    },

    password: {
        type: String,
        select: false
    },

    plainPassword: {
        type: String,
        select: false
    }

});

// FIXME: password encoding only on change, not always
userSchema.pre('save', function(next) {
    // check if a plainPassword was set
    if (this.plainPassword !== '') {
        // generate salt
        crypto.randomBytes(64, function(err, buf) {
            if (err) return next(err);
            this.salt = buf.toString('base64');
            // encode password
            crypto.pbkdf2(this.plainPassword, this.salt, 25000, 512, function(err, encodedPassword) {
                if (err) return next(err);
                this.password = new Buffer(encodedPassword, 'binary').toString('base64');
                this.plainPassword = '';
            }.bind(this));
        }.bind(this));
    }

    next();
});

// statics
userSchema.methods.hasEqualPassword = function(plainPassword, cb) {
    crypto.pbkdf2(plainPassword, this.salt, 25000, 512, function(err, encodedPassword) {
        if (err) return next(err);
        encodedPassword = new Buffer(encodedPassword, 'binary').toString('base64');
        cb((this.password === encodedPassword));
    }.bind(this));
}

module.exports = mongoose.model('User', userSchema, 'Users');

誰かが暗号化をマングースセッターに移すことができましたか?

よろしく、bodo

4

1 に答える 1

1

thisキーワードを使用して、セッター内から他のプロパティにアクセスできます。例えば:

userSchema.path('pass').set(function(v) {

  console.log(this); // Returns model instance

  return v;

});

ただし、セッターはユースケースには適していません。ご存知かもしれませんが、HMAC-SHA1は非常に高価であるため、非同期で実行しない限りブロックされます。マングースセッターは値を返す関数を必要とし、crypto.pbkdf2()のコールバックの結果をセッター関数の戻り値にルーティングする方法はありません。これは非同期JavaScriptの制限であり、Mongoose自体ではありません。非同期チェーンの性質を破壊するため、同期関数内で非同期呼び出しをラップすることはできません。

セッターは、単純な文字列操作とデータのサニタイズに最も広く使用されています。

インスタンスメソッドのみを使用した暗号化のデモを次に示します。

// Model method
userSchema.methods.hashPassword = function(pass, callback) {
  // Generate salt (this should probably be async too)
  var salt = this.salt = crypto.createHash('md5').update(Math.random().toString()).digest('hex');
  // Salt and Hash password
  crypto.pbkdf2(pass, salt, 25000, 512, callback);
});

// Implementation
var user = new User({
  email: req.body.email
});
user.hashPassword(req.body.pass, function(err, hash){
  user.pass = hash; 
  user.save();
});
于 2012-11-05T21:27:51.073 に答える