网站在登录前,需要进行注册收集用户基本信息,bcrypt 提供密码加密验证的方法,但是使用不正确,会给初学者带来各种问题。

bcrypt 的安装:

npm i bcrypt

经过测试,经常安装不成功,原因和node.js的版本有原因,我在 下面这篇文章中有记录解决办法:

bcrypt 安装不成功解决办法

但也不是万能的,如果还不能解决的话,可以尝试给 bcrypt 指定版本号安装:

npm install --save bcrypt@2.0.1

一般是会成功的!!

用户在注册时,除了收集用户信息外,因为要用到 bcrypt ,必须要在注册时对密码进行加密,加密后再保存到数据库中。因为用户登录时,使用 bcrypt 的 compare 方法,这个方法是验证加密的密码的,如果在注册时没有加密,而登录时使用 compare 进行验证,直接会导致,将 mongodb 直接挂掉!而且登录也不会成功,也不报错,也不提示的这种尴尬的局面,会导致无从下手。

bcrypt  注册的逻辑:

  1. 收集用户(表单)的基本信息
  2. bcrypt.genSalt() 给密码加密
  3. 加密完成,将数据保存在数据库
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 功能单一,支持本地账号验证和第三方账号登录验证,这里用到了本地用户登录验证。它本身不能作验证,它主要是用来验证请求的,是由 passport 与 local-passport 搭配使用的。
  • bcrypt 是单向的,跨平台的文件加密工具,经过它加密的密码,口令为8~56个字符,并在内容被转化为 448 位的密钥,在加密算法领域,越慢的加密算法越安全,bcrypt 比 md5 还要慢,因此它的算法是比较安全的,黑客破解成本高。因 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 进行验证:

npm install passport --save
npm install passport-local --save

默认本地验证是通过用户名和密码来进行验证的,需要对 Strategies 进行配置:

assport.use(new LocalStrategy(
function(username, password, done) {
//操作
})
})

我这个项目是使用邮箱和密码来进行验证的,方法有所不同:

passport.use(new LocalStrategy({usernameField: 'email'}, (email, password, done) => {
//操作
  }))
LocalStrategy 的第一个参数对象为一个字符串,用来说明是用户验证是的是一个 email;
          第二个参数是从 passport 方法中获取并传回来的表单中的值,也就是要验证的字段。
          第二个参数中的 done 为验证回调,在passport.use()里面,done()有三种用法
  • 当发生系统级异常时,返回done(err),这里是数据库查询出错
  • 当验证不通过时,返回done(null, false, message),这里的message是可选的,可通过express-flash调用。express-flash 为验证提示信息:登录成功 / 登录失败
  • 当验证通过时,返回done(null, user)

login 在这里的登录方法,登录过程中的密码验证在 passport.js 中一起操作:

const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const bcrypt = require('bcrypt');
const passport = require('passport');
const urlencodedParser = bodyParser.urlencoded({ extended: false });

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,包括下列属性:

  • session:Boolean。设置是否需要session,默认为true
  • successRedirect:String。设置当验证成功时的跳转链接
  • failureRedirect:String。设置当验证失败时的跳转链接
  • failureFlash:Boolean or String。设置为Boolean时,express-flash将调用use()里设置的message。设置为String时将直接调用这里的信息。
  • successFlash:Boolean or String。使用方法同上。

第三个参数是callback。


const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
// Load user model
const UserSchema = require('../models/UserSchema');
 
module.exports = function(passport){
  passport.use(new LocalStrategy({usernameField: 'email'}, (email, password, done) => {
  console.log('获取的字段:' + email+'/'+ password)
  // Match user
  UserSchema.findOne({
    email:email
  }).then(users => {
    console.log('user存在吗?' + users)
    if(!users){
      return done(null, false, {message: 'No User Found'});
    }
  // Match password
  bcrypt.compare(password, users.password, (err, isMatch) => {
    console.log('password ' + password);
    console.log('user.password' + users.password);
    if(err) throw err;
    if(isMatch){
      console.log('isMatch ' + isMatch)
      return done(null, users);
    } else {
      return done(null, false, {message: 'Password Incorrect'});
    }
  })
 })
}));

/**下面两个方法是用来对数据进行序列化的
* 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);
});
});
}

登录验证方法还没有完全搞懂,如果哪里有不对的地方,欢迎指正。

网站注册与登录使用 bcrypt与 passport 双重验证 解释的更多相关文章

  1. django-auth组件的注册,登录,登出,及验证是否已经登入。使用login的属性

    1.注册: 1.创建User(django自带的用户model)的form对象 定义form验证返回的错误提示信息 error_msg = { 'username': {'required': '用户 ...

  2. 学习MVC之租房网站(八)- 前台注册和登录

    在上一篇<学习MVC之租房网站(七)-房源管理和配图上传>完成了在后台新增.编辑房源信息以及上传房源配图的功能.到此后台开发便告一段落了,开始实现前台的功能,也是从用户的登录.注册开始. ...

  3. 利用angular4和nodejs-express构建一个简单的网站(五)—用户的注册和登录-HttpClient

    上一节简单介绍了一下利用angular构建的主路由模块,根据上一节的介绍,主页面加载时直接跳转到用户管理界面,下面就来介绍一下用户管理模块.启动应用后,初始界面应该是这样的: 用户管理模块(users ...

  4. 网站实现微信登录之回调函数中登录逻辑的处理--基于yii2开发的描述

    上一篇文章网站实现微信登录之嵌入二维码中描述了如何在自己的登录页面内嵌入登录二维码,今天的这篇文章主要是描述下在扫码成功之后微信重定向回网站后登录逻辑的处理,其实也就是验证身份信息,授权用户登录的逻辑 ...

  5. 多平台的网站实现单点登录系统(SSO)的开发思路 让你的会员中心更加统一(参考资料)

    单点登录并不是一个新鲜的玩意儿,比较官方的解释是企业业务整合的解决方案之一,通俗来讲SSO就是一个通用的用户中心,国内比较流行的UCenter就是一套单点登录解决方案.而近期以CSDN明文存储用户密码 ...

  6. PHP开发网站之微信登录、绑定

    )))刷新access_token()); ); ); curl_setopt($curlobj, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curlo ...

  7. 网站集成QQ登录功能

    最近在做一个项目时,客户要求网站能够集成QQ登录的功能,以前没做过这方面的开发,于是去QQ的开放平台官网研究了一下相关资料,经过自己的艰苦探索,终于实现了集成QQ登录的功能,现在把相关的开发经验总结一 ...

  8. PC 端微信扫码注册和登录

    一.前言 先声明一下,本文所注重点为实现思路,代码及数据库设计主要为了展现思路,如果对代码效率有着苛刻要求的项目切勿照搬. 相信做过微信开发的人授权这块都没少做过,但是一般来说我们更多的是为移动端的网 ...

  9. 网站集成QQ登录功能(转)

    最近在做一个项目时,客户要求网站能够集成QQ登录的功能,以前没做过这方面的开发,于是去QQ的开放平台官网研究了一下相关资料,经过自己的艰苦探索,终于实现了集成QQ登录的功能,现在把相关的开发经验总结一 ...

随机推荐

  1. 服务端预渲染之Nuxt(介绍篇)

    现在前端开发一般都是前后端分离,mvvm和mvc的开发框架,如Angular.React和Vue等,虽然写框架能够使我们快速的完成开发,但是由于前后台分离,给项目SEO带来很大的不便,搜索引擎在检索的 ...

  2. HTML5最佳实践web app

    简介 本文重点关注如何充分利用HTML5和CSS让web app运行更加流畅. Tip 1: 使用web storage代替cookie cookie最大的缺陷是在每一次HTTP请求中都会携带所有符合 ...

  3. Android之Material Dialogs详解

    文章大纲 一.什么是Material Dialogs二.Material Dialogs实战三.项目源码下载   一.什么是Material Dialogs   Material Dialogs是一个 ...

  4. SVN使用规范

    1.提交之前先更新.当完成功能之后,首先检查自己修改了什么 ,然后通过编译并且自己测试之后,谨慎地提交,不可强行提交. 2.在更新时注意所更新文件的列表,如果提交过程中产生了更新,也需要重新编译并且完 ...

  5. ambari2.6.50 openssl 版本问题:SSLError: Failed to connect. Please check openssl library versions. Openssl error upon host registration

    I'm trying to register hostnames in Ambari but getting the error below. We tried to run yum update o ...

  6. vue 预渲染遇到的坑

    前言: 最近公司项目需要增加seo搜索引擎优化,到网上找了下资料,有预渲染和服务端渲染两种方式,考虑到只需要渲染首页所以我选择了先启用比较简单的预渲染方式来做seo! 步骤: 1.安装 prerend ...

  7. qml demo分析(abstractitemmodel-数据分离)

    一.概述 qt5之后qml也可以被用于桌面程序开发,今天我就拿出qt demo中的一个qml示例程序进行分析.这个demo主要是展示了qml数据和展示分离的使用方式,qml只专注于快速高效的绘制界面, ...

  8. Flink从入门到放弃(入门篇3)-DataSetAPI

    戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...

  9. 使用java语言,将字符串中连续重复出现的字母变成“出现次数“+字母的格式

    今天在简书上看到这样一道有趣的算法题: 解题思路 首先定义一个变量element,默认是字符串的第一个字符.以element为基准元素,去判断某个字符是否重复.然后再去定义一个变量count去记录重复 ...

  10. c#文件图片操作

    系统特殊目录路径 //取得特殊文件夹的绝对路径 //桌面 Environment.GetFolderPath(Environment.SpecialFolder.Desktop); //收藏夹 Env ...