bcrypt 處理密碼及處理警告訊息

為資料庫的使用者密碼加鹽,將在資料庫的密碼 明碼(plain text)做雜湊處理。

bcrypt

是為 密碼雜湊函式(password hashing),根據 Blowfish 加密演算設計。

詳細看 wikipedia

  1. 在使用者設定的密碼上,加上一段隨機字串(稱為salt),將它組合起來。
  2. 使用的是雜湊演算(hashing algorithm),產生 hashed password
  3. 將 hashed password 跟中途加入的 salt 分開儲存。
  4. 使用者嘗試登入處理後,如果字串與資料庫 hashed password 相同,即為成功,不一致失敗。
  5. 雜湊處理過後的字串無法還原。表示沒法解出原貌。

加密(encryption)與密碼雜湊(password hashing)不同

bcrypt 實作

  1. 安裝 bcryptjs = bcrypt.js
  2. 修改路由,使用 bcrypt 處理註冊密碼
  3. 修改 passport middleware,處理登入密碼與資料庫比對。

安裝

npm install bcryptjs

修改路由

在註冊中判斷是否為新使用者後,使用 加鹽 的方式,將新使用者資料做雜湊處理。

注意使用到 JS 中的 throw 用法, throw 拋出後給 .catch 處理。

user.js

const express = require('express')
const passport = require('passport')
const router = express.Router()
const bcrypt = require('bcryptjs') //載入 bcryptjs

// 送出註冊時檢查
router.post('/register', (req, res) => {
const { name, email, password, password2 } = req.body
User.findOne({ email: email}).then(user =>{
if (user) {
//略
} else {
const newUser = new User({
name,
email,
password
})
bcrypt.genSalt(10, (err, salt) =>
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err
newUser.password = hash

newUser
.save()
.then(user => {
res.redirect('/')
})
.catch(err => console.log(err))
})
)
}
})
})

由於我們做了密碼的雜湊處理,所以在登入部分也需要修改 passport 檢查使用者密碼的部分,使用 bcrypt.compare 函式比對輸入的密碼是否與資料庫內容一致。

config/passport.js

const LocalStrategy = require('passport-local').Strategy
const mongoose = require('mongoose')
const bcrypy = require('bcryptjs')
const User = require('../models/user.js')

module.exports = passport => {
passport.use(
new LocalStrategy({ usernameField: 'email'}, (email, password, done) => {
User.findOne({ email: email }).then(user => {
if (!user) {
return done(null, false, {message: 'That email is not registered'})
}
bcrypt.compare(password, user.password, (err, isMatch) => {
if (isMatch) {
return done(null, user)
} else {
return done(null, false, {message: 'Email and password incorrect'})
}
})
})
})
)
}

原本為

if (user.password != password) {
return done(null, false, {message: 'Email or Password incorrect'})
}
return done(null, user)

改成

bcrypt.compare(password, user.password, (err, isMatch) => {
if (isMatch) {
return done(null, user)
} else {
return done(null, false, {message: 'Email and password incorrect'})
}
})

在 commend line 的警告訊息

在設定完前面實作後,可以發現 command line 出現了

express-session deprecated undefined resave option; provide resave option
express-session deprecated undefined savaUninitialized option; provide saveUninitialized option
(node:xxxxx) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndex instead.

前兩項為 Express-session warnings : 關於 resave 和 saveUninitialized。

  • resave: ture 與使用者互動後,強制將 session 更新到 session store。
  • saveUninitialized: 強制將為初始化的 session 存回 session store。為初始表示是新的,例如為登入的使用者 session。

第三項為 mongoose warning,問題發生源在認證登入,建立關聯時,增加 userId 屬性,並設為 index。

express session warning in app.js

app.use(session({
secret: 'secret key' // 自定義的字串用來處理雜湊
resave: 'false',
saveUninitialized: 'false'
}))

mongoose warning in app.js

mongoose.connect('mongodb://localhost/todo', { userNewUrlParser: ture, useCreateIndex: true }) // 新增 useCreateIndex: true