網站在登陸前,須要進行註冊收集用戶基本信息,bcrypt 提供密碼加密驗證的方法,可是使用不正確,會給初學者帶來各類問題。html
bcrypt 的安裝:node
npm i bcrypt
通過測試,常常安裝不成功,緣由和node.js的版本有緣由,我在 下面這篇文章中有記錄解決辦法:算法
但也不是萬能的,若是還不能解決的話,能夠嘗試給 bcrypt 指定版本號安裝:mongodb
npm install --save bcrypt@2.0.1
通常是會成功的!!數據庫
用戶在註冊時,除了收集用戶信息外,由於要用到 bcrypt ,必需要在註冊時對密碼進行加密,加密後再保存到數據庫中。由於用戶登陸時,使用 bcrypt 的 compare 方法,這個方法是驗證加密的密碼的,若是在註冊時沒有加密,而登陸時使用 compare 進行驗證,直接會致使,將 mongodb 直接掛掉!並且登陸也不會成功,也不報錯,也不提示的這種尷尬的局面,會致使無從下手。express
bcrypt 註冊的邏輯:npm
router.post('/register',urlencodedParser,(req,res) => { //驗證 const newUser = new UserSchema({ email: req.body.email, password:req.body.password, confirmPassword:req.body.confirmPassword, firstName:req.body.firstName, lastName:req.body.lastName }); console.log('body: ' + newUser) //給 newUser.password 加密,hash 爲加密後的密碼 bcrypt.genSalt(10, function(err, salt) { bcrypt.hash(newUser.password, salt, (err, hash) => { if(err) throw err; newUser.password = hash; //保存到數據庫 newUser.save().then((user) => { res.redirect('/admin/login'); res.send(user); }).catch((err) => { res.render('/admin/register',{}) }) }); }); });
res.redirect() 爲跳轉到哪一個路徑
註冊成功以後,直接跳轉到 login 頁面。
登陸相對比較複雜,會用到 passport 與 bcrypt 進行驗證。
登陸方法也能夠不使用 passport 登陸賬號驗證,僅使用 bcrypt 進行密碼驗證:安全
const express = require('express'); const router = express.Router(); const bodyParser = require('body-parser'); const bcrypt = require('bcrypt'); const urlencodedParser = bodyParser.urlencoded({ extended: false }); require('../models/UserSchema'); const UserSchema = mongoose.model('users'); router.post("/login",urlencodedParser,(req,res,next) => { const loginUser = { email:req.body.email, password:req.body.password }; console.log(loginUser); UserSchema.findOne({ email:loginUser.email }).then(users => {if(!users){ return done(null, false, {message: 'No User Found'}); } //驗證密碼 bcrypt.compare(loginUser.password, users.password, (err, isMatch) => { if(err) throw err; if(isMatch){ res.redirect('/') } else { res.redirect('/admin/login') } }) }) });
同時使用 passport 與 bcrypt 進行驗證:session
npm install passport --save
npm install passport-local --save
默認本地驗證是經過用戶名和密碼來進行驗證的,須要對 Strategies 進行配置:mongoose
assport.use(new LocalStrategy( function(username, password, done) { //操做 }) })
我這個項目是使用郵箱和密碼來進行驗證的,方法有所不一樣:
passport.use(new LocalStrategy({usernameField: 'email'}, (email, password, done) => { //操做
LocalStrategy 的第一個參數對象爲一個字符串,用來講明是用戶驗證是的是一個 email;
第二個參數是從 passport 方法中獲取並傳回來的表單中的值,也就是要驗證的字段。
第二個參數中的 done 爲驗證回調,在passport.use()裏面,done()有三種用法
login 在這裏的登陸方法,登陸過程當中的密碼驗證在 passport.js 中一塊兒操做:
router.post("/login",urlencodedParser,(req,res,next) => { const loginUser = { email:req.body.email, password:req.body.password }; console.log(loginUser); passport.authenticate('local', { successRedirect:'/', failureRedirect: '/admin/login', failureFlash: true })(req, res, next); })
這裏的passport.authenticate(‘local’)就是中間件,若經過就進入後面的回調函數,而且給res加上res.user,若不經過則默認返回401錯誤。
authenticate()方法有3個參數,第一是name,即驗證策略的名稱,第二個是options,包括下列屬性:
第三個參數是callback。
/**下面兩個方法是用來對數據進行序列化的 * serializeUser 將users.id序列化到session中 * deserializeUser 若id存在則從數據庫中查詢users並存儲與req.users中 * * 此處的 users 爲表名 */ passport.serializeUser(function(users, done) { done(null, users.id); }); passport.deserializeUser(function(id, done) { UserSchema.findById(id, function(err, users) { done(err, users); }); }); }
登陸驗證方法尚未徹底搞懂,若是哪裏有不對的地方,歡迎指正。