网站在登陆前,须要进行注册收集用户基本信息,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); }); }); }
登陆验证方法尚未彻底搞懂,若是哪里有不对的地方,欢迎指正。