Mongoose password hashing

前端 未结 10 951
盖世英雄少女心
盖世英雄少女心 2020-12-04 07:28

I am looking for a good way to save an Account to MongoDB using mongoose.

My problem is: The password is hashed asynchronously. A setter wont work here because it on

相关标签:
10条回答
  • 2020-12-04 07:34

    The mongodb blog has an excellent post detailing how to implement user authentication.

    http://blog.mongodb.org/post/32866457221/password-authentication-with-mongoose-part-1

    The following is copied directly from the link above:

    User Model

    var mongoose = require('mongoose'),
        Schema = mongoose.Schema,
        bcrypt = require('bcrypt'),
        SALT_WORK_FACTOR = 10;
         
    var UserSchema = new Schema({
        username: { type: String, required: true, index: { unique: true } },
        password: { type: String, required: true }
    });
         
    UserSchema.pre('save', function(next) {
        var user = this;
    
        // only hash the password if it has been modified (or is new)
        if (!user.isModified('password')) return next();
    
        // generate a salt
        bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
            if (err) return next(err);
    
            // hash the password using our new salt
            bcrypt.hash(user.password, salt, function(err, hash) {
                if (err) return next(err);
                // override the cleartext password with the hashed one
                user.password = hash;
                next();
            });
        });
    });
         
    UserSchema.methods.comparePassword = function(candidatePassword, cb) {
        bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
            if (err) return cb(err);
            cb(null, isMatch);
        });
    };
         
    module.exports = mongoose.model('User', UserSchema);
    

    Usage

    var mongoose = require(mongoose),
        User = require('./user-model');
         
    var connStr = 'mongodb://localhost:27017/mongoose-bcrypt-test';
    mongoose.connect(connStr, function(err) {
        if (err) throw err;
        console.log('Successfully connected to MongoDB');
    });
         
    // create a user a new user
    var testUser = new User({
        username: 'jmar777',
        password: 'Password123'
    });
         
    // save the user to database
    testUser.save(function(err) {
        if (err) throw err;
    });
        
    // fetch the user and test password verification
    User.findOne({ username: 'jmar777' }, function(err, user) {
        if (err) throw err;
         
        // test a matching password
        user.comparePassword('Password123', function(err, isMatch) {
            if (err) throw err;
            console.log('Password123:', isMatch); // -> Password123: true
        });
         
        // test a failing password
        user.comparePassword('123Password', function(err, isMatch) {
            if (err) throw err;
            console.log('123Password:', isMatch); // -> 123Password: false
        });
    });
    
    0 讨论(0)
  • 2020-12-04 07:36

    Another way to do this using virtuals and instance methods:

    /**
     * Virtuals
     */
    schema.virtual('clean_password')
        .set(function(clean_password) {
            this._password = clean_password;
            this.password = this.encryptPassword(clean_password);
        })
        .get(function() {
            return this._password;
        });
    
    schema.methods = {
    
        /**
         * Authenticate - check if the passwords are the same
         *
         * @param {String} plainText
         * @return {Boolean}
         * @api public
         */
        authenticate: function(plainPassword) {
            return bcrypt.compareSync(plainPassword, this.password);
        },
    
        /**
         * Encrypt password
         *
         * @param {String} password
         * @return {String}
         * @api public
         */
        encryptPassword: function(password) {
            if (!password)
                return '';
    
            return bcrypt.hashSync(password, 10);
        }
    };
    

    Just save your model like, the virtual will do its job.

    var user = {
        username: "admin",
        clean_password: "qwerty"
    }
    
    User.create(user, function(err,doc){});
    
    0 讨论(0)
  • 2020-12-04 07:40

    const bcrypt = require('bcrypt');
    
    const saltRounds = 5;
    const salt = bcrypt.genSaltSync(saltRounds);
    
    module.exports = (password) => {
      return bcrypt.hashSync(password, salt);
    }

    const mongoose = require('mongoose')
    const Schema = mongoose.Schema
    const hashPassword = require('../helpers/hashPassword')
    
    const userSchema = new Schema({
      name: String,
      email: {
        type: String,
        match: [/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, `Please fill valid email address`],
        validate: {
          validator: function() {
            return new Promise((res, rej) =>{
              User.findOne({email: this.email, _id: {$ne: this._id}})
                  .then(data => {
                      if(data) {
                          res(false)
                      } else {
                          res(true)
                      }
                  })
                  .catch(err => {
                      res(false)
                  })
            })
          }, message: 'Email Already Taken'
        }
      },
      password: {
        type: String,
        required: [true, 'Password required']
      }
    });
    
    userSchema.pre('save', function (next) {
      if (this.password) {
          this.password = hashPassword(this.password)
      }
      next()
    })
    
    const User = mongoose.model('User', userSchema)
    
    module.exports = User

    0 讨论(0)
  • 2020-12-04 07:43

    For those who are willing to use ES6+ syntax can use this -

    const bcrypt = require('bcryptjs');
    const mongoose = require('mongoose');
    const { isEmail } = require('validator');
    
    const { Schema } = mongoose;
    const SALT_WORK_FACTOR = 10;
    
    const schema = new Schema({
      email: {
        type: String,
        required: true,
        validate: [isEmail, 'invalid email'],
        createIndexes: { unique: true },
      },
      password: { type: String, required: true },
    });
    
    schema.pre('save', async function save(next) {
      if (!this.isModified('password')) return next();
      try {
        const salt = await bcrypt.genSalt(SALT_WORK_FACTOR);
        this.password = await bcrypt.hash(this.password, salt);
        return next();
      } catch (err) {
        return next(err);
      }
    });
    
    schema.methods.validatePassword = async function validatePassword(data) {
      return bcrypt.compare(data, this.password);
    };
    
    const Model = mongoose.model('User', schema);
    
    module.exports = Model;
    
    0 讨论(0)
  • 2020-12-04 07:50
    const mongoose = require('mongoose');
    var bcrypt = require('bcrypt-nodejs');
    SALT_WORK_FACTOR = 10;
    
    const userDataModal = mongoose.Schema({
        username: {
            type: String,
            required : true,
            unique:true
        },
        password: {
            type: String,
            required : true
        }
    
    });
    
    userDataModal.pre('save', function(next) {
        var user = this;
    
        // only hash the password if it has been modified (or is new)
        if (!user.isModified('password')) return next();
    
        // generate a salt
        bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
            if (err) return next(err);
    
            // hash the password using our new salt
            bcrypt.hash(user.password, salt, null, function(err, hash) {
                if (err) return next(err);
    
                // override the cleartext password with the hashed one
                user.password = hash;
                next();
            });
        });
    });
    
    userDataModal.methods.comparePassword = function(candidatePassword, cb) {
        bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
            if (err) return cb(err);
            cb(null, isMatch);
        });
    };
    
    
    // Users.index({ emaiId: "emaiId", fname : "fname", lname: "lname" });
    
    const userDatamodal = module.exports = mongoose.model("usertemplates" , userDataModal)
    
    
    
    //inserting document
         userDataModel.findOne({ username: reqData.username }).then(doc => {
                console.log(doc)
                if (doc == null) {
                    let userDataMode = new userDataModel(reqData);
                   // userDataMode.password = userDataMode.generateHash(reqData.password);
                    userDataMode.save({new:true}).then(data=>{
                              let obj={
                                  success:true,
                                  message: "New user registered successfully",
                                  data:data
                              }
                                resolve(obj)
                    }).catch(err=>{
                                    reject(err)
                    })
    
                }
                else {
                    resolve({
                        success: true,
                        docExists: true,
                        message: "already user registered",
                        data: doc
                    }
                    )
                }
    
            }).catch(err => {
                console.log(err)
                reject(err)
            })
    
    //retriving and checking
          // test a matching password
                    user.comparePassword(requestData.password, function(err, isMatch) {
                        if (err){ 
    
                            reject({
                                'status': 'Error',
                                'data': err
                            });
    
                            throw err;
                        } else  {
                            if(isMatch){
    
                                resolve({   
                                    'status': true,
                                    'data': user,
                                    'loginStatus' : "successfully Login"
                                });
    
                                console.log('Password123:', isMatch); // -&gt; Password123: true
    
                            }
    
    0 讨论(0)
  • 2020-12-04 07:53

    My refer i think need input PWD hashed input to function compare

    Controller

            let newUser = new User(req.body);
            User.findOne({ username: req.body.username }, function(err, User) {
                if (err) throw err;
                // test a matching password
                newUser.comparePassword(req.body.pwd,User.pwd, function(err, isMatch) {
                    if (err) throw err;
                    console.log(req.body.pwd, isMatch);
                    
                    if(isMatch!=0){
                        //compare false
                        newUser.save((err, User) => {
                            if(err){
                                res.send(err);
                            }    
                            res.json(User);
                        });
                    } else {
                        //// compare false
                    }
                });
            });
    

    Model

    UserSchema.methods.comparePassword = function(candidatePassword:string,foundPWD:string, cb):void {
          bcrypt.compare(candidatePassword,foundPWD, (err, isMatch) => {
            if (err) return cb(err);
            console.log(foundPWD);
            cb(null, isMatch);    
      });
    }
    

    Hope Helpfully

    0 讨论(0)
提交回复
热议问题