為資料庫的使用者密碼加鹽
,將在資料庫的密碼 明碼(plain text)
做雜湊處理。
bcrypt
是為 密碼雜湊函式(password hashing)
,根據 Blowfish 加密演算
設計。
詳細看 wikipedia
- 在使用者設定的密碼上,加上一段隨機字串(稱為salt),將它組合起來。
- 使用的是
雜湊演算(hashing algorithm)
,產生hashed password
。 - 將 hashed password 跟中途加入的 salt 分開儲存。
- 使用者嘗試登入處理後,如果字串與資料庫 hashed password 相同,即為成功,不一致失敗。
- 雜湊處理過後的字串無法還原。表示沒法解出原貌。
加密(encryption)與密碼雜湊(password hashing)不同
bcrypt 實作
- 安裝 bcryptjs = bcrypt.js
- 修改路由,使用 bcrypt 處理註冊密碼
- 修改 passport middleware,處理登入密碼與資料庫比對。
安裝
npm install bcryptjs |
修改路由
在註冊中判斷是否為新使用者後,使用 加鹽
的方式,將新使用者資料做雜湊處理。
注意使用到 JS 中的 throw 用法, throw 拋出後給 .catch 處理。
user.jsconst 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.jsconst 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.jsapp.use(session({
secret: 'secret key' // 自定義的字串用來處理雜湊
resave: 'false',
saveUninitialized: 'false'
}))
mongoose warning in app.jsmongoose.connect('mongodb://localhost/todo', { userNewUrlParser: ture, useCreateIndex: true }) // 新增 useCreateIndex: true