使用mongoose和bcrypt實現用戶密碼加密

前面的話

  最近在作的我的項目中,須要對密碼進行加密保存,對該操做的詳細步驟記錄以下html

 

介紹

  關於mongoose已經寫過博客就再也不贅述,下面主要介紹bcryptnode

  bcrypt是一個由兩個外國人根據Blowfish加密算法所設計的密碼散列函數。實現中bcrypt會使用一個加鹽的流程以防護彩虹表攻擊,同時bcrypt仍是適應性函數,它能夠藉由增長迭代之次數來抵禦暴力破解法算法

  使用npm安裝便可mongodb

npm install --save bcrypt

  注意:bcrypt之前是能夠直接安裝的,可是最近發現沒法正常安裝,可使用cnpm安裝bcryptjs來替代數據庫

cnpm install --save bcryptjs
const bcrypt = require('bcryptjs')

 

用戶模型

  下面來建立代碼用戶user的schema,用戶名不能重複npm

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    bcrypt = require('bcrypt');
var UserSchema = new Schema({ username: { type: String, required: true, index: { unique: true } }, password: { type: String, required: true } }); module.exports = mongoose.model('User', UserSchema);

 

加密

  下面加入用戶模型的是Mongoose的中間件,該中間件使用pre前置鉤子,在密碼保存以前,自動地把密碼變成hash。詳細代碼以下mongoose

let SALT_WORK_FACTOR = 5
UserSchema.pre('save', function(next) {
    var user = this;

    //產生密碼hash當密碼有更改的時候(或者是新密碼)
    if (!user.isModified('password')) return next();

    // 產生一個salt
    bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
        if (err) return next(err);

        //  結合salt產生新的hash
        bcrypt.hash(user.password, salt, function(err, hash) {
            if (err) return next(err);

            // 使用hash覆蓋明文密碼
            user.password = hash;
            next();
        });
    });
});

  在node.bcrypt.js中SALT_WORK_FACTOR默認使用的是10,這裏設置爲5ide

 

驗證

  加密以後,密碼原文被替換爲密文了。咱們沒法解密,只能經過bcrypt的compare方法,對再次傳入的密碼和數據庫中保存的加密後的密碼進行比較,若是匹配,則登陸成功函數

UserSchema.methods.comparePassword = function(candidatePassword, cb) {
    bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
        if (err) return cb(err);
        cb(null, isMatch);
    });
};

  把上面的幾個步驟串在一塊兒,完整代碼以下測試

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    bcrypt = require('bcrypt'),
    SALT_WORK_FACTOR = 5;

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);

 

測試

  把上面的代碼保存成user-model.js,而後運行下面代碼來實際測試

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 user to database
testUser.save(function(err) {
    if (err) throw err;

    // fetch 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
        });
    });
});

  控制檯中輸入以下數據:

  數據庫數據以下:

相關文章
相關標籤/搜索