nodejs+express+mongodb实现登录注册

1 简介

  • 登录注册功能使用nodejs+express+mongodb完成,其中对mongodb的操作使用mongoose完成,对mongodb的可视化查看使用mongo compass完成。参考了幕课网node+mongodb 建站攻略(一期)教程。
  • 主要添加或修改了app.js, api.js,mongo.js, router.js, login.js,register.js。
  • 参考网上教程实现了验证码功能,并对密码进行了加盐hash。
  • 优化界面UI,使用sweetalert美化弹窗显示。
  • 测试命令为npm run start,访问localhost:3000/可达主页,选择右上方登录注册即可。

2 具体实现

2.1 基本框架搭建

  • 使用npm系列命令安装相关依赖,express命令来生成目录。

  • 在app.js加载初始化依赖模块并配置,在router.js添加路由信息。在mongo.js连接数据库。

    //在app.js加载初始化依赖模块并配置
    var createError = require('http-errors');
    var express = require('express');
    var path = require('path');
    var cookieParser = require('cookie-parser');
    var logger = require('morgan');
    var ejs = require('ejs');
    var session = require('express-session');
    var router = require('./routes/router'); var app = express(); // view engine setup
    app.set('views', path.join(__dirname, 'views'));
    app.engine('html', ejs.__express);
    app.set('view engine', 'html'); app.use(logger('dev'));
    app.use(express.json());
    app.use(express.urlencoded({ extended: false }));
    app.use(cookieParser());
    app.use(express.static(path.join(__dirname, 'public')));
    app.use('/', router); //在router.js添加路由信息
    router.get('/', function(req, res, next) {
    res.redirect('/home');
    }); router.get('/home', function(req, res) {
    res.render('home');
    }) router.get('/login', function(req, res) {
    res.render('login');
    }) router.get('/register', function(req, res) {
    res.render('register');
    })
    //在mongo.js连接数据库
    var mongoose = require('mongoose');
    mongoose.connect('mongodb://localhost:27017/SightSeeing', {
    useNewUrlParser: true,
    useUnifiedTopology: true
    })
    .then(() => console.log('数据库连接成功!'))
    .catch(err => console.log(err, '数据库连接失败!')); var userSchema = new mongoose.Schema({
    email: String,
    password: String
    });
    var User = mongoose.model('User', userSchema);
    module.exports = User;
  • 登录注册具体实现将在下文阐述。

2.2 验证码

  • 验证码生成与验证码检验

    参考https://blog.csdn.net/askd23456789/article/details/94741605

    //验证码生成
    function createCode(length) {
    var code = "";
    var codeLength = parseInt(length); //验证码的长度
    var checkcode = document.getElementById("checkcode");
    ////所有候选组成验证码的字符,当然也可以用中文的
    var codeChars = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
    //循环组成验证码的字符串
    for (var i = 0; i < codeLength; i++) {
    //获取随机验证码下标
    var charNum = Math.floor(Math.random() * 62);
    //组合成指定字符验证码
    code += codeChars[charNum];
    }
    if (checkcode) {
    //将生成验证码赋值到显示区
    checkcode.innerHTML = code;
    }
    }
    //验证码验证
    if (inputcode.length <= 0) {
    swal({
    title: "请输入验证码!",
    type: "warning",
    confirmButtonText: "确定"
    })
    } else if (inputcode.toUpperCase() != checkcode.toUpperCase()) {
    swal({
    title: "验证码输入有误!",
    type: "warning",
    confirmButtonText: "确定"
    })
    createCode(4);
    }
  • 验证码效果示例

2.3 弹窗插件

  • 代码

    <!--添加依赖-->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
    <!--配置示例-->
    swal({
    title: res.message,
    type: "warning",
    confirmButtonText: "确定"
    })
  • 效果示例

    • 在2.2可以看到

2.4 输入检查

  • 正则函数(注册)

    // 检验邮箱是否合法
    function isEmail(email) {
    var reg = /^[A-Za-z0-9]+([._\\-]*[A-Za-z0-9])*@([A-Za-z0-9]+[-A-Za-z0-9]*[A-Za-z0-9]+\.){1,63}[A-Za-z0-9]+$/;
    return reg.test(email);
    }
    //检测密码是否合法
    function isPassword(email) {
    var reg = /^.*(?=.{6,})(?=.*[a-zA-Z]).*$/;
    return reg.test(email);
    }
  • 检查

    //这里以注册举例
    if (isEmail(email) == false) {
    swal({
    title: "邮箱不合法!",
    text: "请重新输入邮箱",
    type: "warning",
    confirmButtonText: "确定"
    })
    } else if (pwd1 != pwd2) {
    swal({
    title: "两次密码输入不一致!",
    text: "请重新输入第二次密码",
    type: "warning",
    confirmButtonText: "确定"
    })
    } else if (isPassword(pwd1) == false) {
    swal({
    title: "密码不得少于6位,且至少包含一个字母!",
    text: "请重新选择密码",
    type: "warning",
    confirmButtonText: "确定"
    })
    }
  • 检查效果示例

2.5 后台接口逻辑与加盐hash

  • 主要用来验证数据规范性,以注册举例

    router.post('/register', function(req, res) {
    var ema = req.query.email;
    var pwd = req.query.password;
    User.findOne({ email: ema }, function(err, result) {
    if (err) {
    console.log(err);
    res.send({ succeed: false, message: '服务器错误!' });
    } else {
    if (result != null) {
    res.send({ succeed: false, message: '用户名已存在!' });
    } else {
    var hashCode = bcrypt.hashSync(pwd, salt);
    User.create({
    password: hashCode,
    email: ema
    }, function(err1, doc) {
    if (err1) {
    console.log(err1);
    res.send({ succeed: false, message: '注册失败!' });
    } else {
    res.send({ succeed: true, message: '注册成功!' });
    }
    })
    }
    }
    })
    })
  • 加盐hash使用bcryptjs依赖完成

    var salt = bcrypt.genSaltSync(10);  //设置加盐等级
    bcrypt.compareSync(pwd, result.password); //登录时哈希验证
    var hashCode = bcrypt.hashSync(pwd, salt);//注册时加盐哈希加密
  • 数据库可视化展示,可以看见密码不是以明文存储在数据库的,而是经过了加盐hash。

2.6 Ajax传递数据到后端

  • 以登录举例

    $.ajax({
    url: '/mongo/login?email=' + email + '&password=' + pwd,
    type: 'get',
    success: function(res) {
    if (res.succeed) {
    swal({
    title: "登录成功!",
    type: "success",
    confirmButtonText: "确定",
    timer: 1500
    }, function() {
    setTimeout(function() {
    window.location.href = "/home";
    })
    })
    } else {
    swal({
    title: res.message,
    type: "error",
    confirmButtonText: "确定"
    })
    }
    }
    })

2.7 使用session

//app.js使用session
app.use(session({
secret: 'secret',
email: 'email',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}))
//api.js添加session,登录成功,就将email存入session
req.session.email = ema;

3 实验总结

  • 这里记录一下踩过的坑

    • 在app.js中配置session时,必须写在路由配置的上方,否则获取不到参数,报错:Cannot set property ‘xxx‘ of undefined

    • 在npm install xxx后,可以再npm install一下,否则可能依赖添加不完全。

nodejs+express+mongodb实现登录注册的更多相关文章

  1. 【重点突破】—— Nodejs+Express+MongoDB的使用基础

    前言:最近学习vue和react的高阶项目,都需要和Nodejs+Express+MongoDB结合实现全栈开发.这里结合实例Demo和所学项目集中总结一下这部分服务端的基础知识. 一.Express ...

  2. NodeJS+Express+MongoDB

    一.MongoDB MongoDB是开源,高性能的NoSQL数据库:支持索引.集群.复制和故障转移.各种语言的驱动程序丰富:高伸缩性:MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言 ...

  3. nodejs+express中设置登录拦截器

    在nodejs+express中,采用nodejs后端路由控制用户登录后,为了加强前端的安全性控制,阻止用户通过在浏览器地址栏中输入地址访问后台接口,在app.js中需要加入拦截器进行拦截: /*** ...

  4. NodeJS+Express+MongoDB 简单实现数据录入及回显展示【适合新人刚接触学习】

    近期在看NodeJS相关 不得不说NodeJS+Express 进行网站开发是很不错,对于喜欢玩JS的来说真是很好的一种Web开发组合 在接触NodeJS时受平时Java或者C#中API接口等开发的思 ...

  5. nodejs+express+mongodb简单的例子

    简单的介绍下node+express+mongodb这三个东西.node:是运行在服务器端的程序语言,表面上看过去就是javascript一样的东西,但是呢,确实就是服务器语言,个人觉得在一定层次上比 ...

  6. 从无到有,用Nodejs+express+mongodb搭建简易登陆系统

    前端处理server表示很蛋疼,初学Node,虽然感觉异常强大,但是学起来还是有些吃力的,Node是工具,它不是万能的,搭建一个系统还是需要借助其他一些工具,对于我这个没怎么接触server的前端来说 ...

  7. Express+MySQL实现登录注册的demo

    MySQL5.7.20 demo准备 安装MySQL,安装完毕之后添加系统环境变量在cmd中启动服务:net start mysql57,如果是安装MySQL8.0则服务名默认时mysql80,测试安 ...

  8. Nodejs&express+mongodb完成简单用户登录(即Nodejs入门)

    刚了解nodejs,发现nodejs配置起来不复杂,但也有很多需要注意的地方,今天就记录一下,以后也可拿出来看看. 要完成这个简单的示例,从零开始,走三步就行了. 一.搭建开发环境 二.创建项目(ex ...

  9. nodejs+express+mongodb写api接口的简单尝试

    1:启动mongodb服务 我的mongoDB的安装目录:E:\mongoDB\bin,版本:3.4.9 打开cmd  -> e:(进入e盘) -> cd mongoDB/bin(进入mo ...

随机推荐

  1. hdu5893 List wants to travel(树链剖分+线段树)

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submissi ...

  2. Codeforces Round #693 (Div. 3) G. Moving to the Capital (图,dp)

    题意:有一张有向图,每个点的权值为点\(1\)到该点的最短距离(每条边的长度为\(1\)),对于一条路径,这条路径上最多只能有一条边,这条边起点的权值不小于终点,现在要求每个点能到达路径上的点的最小权 ...

  3. Best Reward && Girls' research

    After an uphill battle, General Li won a great victory. Now the head of state decide to reward him w ...

  4. Codeforces Round #635 C. Linova and Kingdom

    传送门:C. Linova and Kingdom 题意:给你一棵树,要求对k个结点涂色,然后统计每个未涂色结点到根结点的路径上未涂色结点的和,求和最大能为多少 题解:对着样例画几遍,然后贪心发现,最 ...

  5. 牛客练习赛70 B.拼凑 (序列自动机)

    题意:有一个模板串,有\(T\)个字符串,从字符串中找到某个子串,使得这个子串中的子序列包含模板串,求最短的子串的长度. 题解:找子序列,很容易想到序列自动机,根据序列自动机的原理,我们一定可以确保除 ...

  6. 2019-2020 ACM-ICPC Brazil Subregional Programming Contest Problem M Maratona Brasileira de Popcorn (二分)

    题意:有\(n\)袋爆米花,某个队伍有\(c\)个队员,每个队员每秒做多可以吃\(t\)粒爆米花,但一袋爆米花只能由一个队员吃完,并且一个队员只能吃连续的一袋或几袋,不能隔着吃某一袋,求将所有爆米花吃 ...

  7. Codeforces Round #656 (Div. 3) C. Make It Good (贪心,模拟)

    题意:给你一个数组\(a\),可以删除其前缀,要求操作后得到的数组是"good"的.对于"good":可以从数组的头和尾选择元素移动到新数组,使得所有元素移动后 ...

  8. 6.PowerShell DSC核心概念之LCM

    什么是LCM? 本地配置管理器 (LCM) 是DSC的引擎. LCM 在每个目标节点上运行,负责分析和执行发送到节点的配置. 它还负责 DSC 的许多方面,包括以下各方面. 确定刷新模式(推送或请求) ...

  9. Mac下anaconda的安装和基本使用

    Mac下anaconda的安装和基本使用 安装 在conda官网下载安装conda. 打开terminal输入conda -V,回车显示conda的版本说明安装成功. 将conda更新到最新版本 co ...

  10. 微信小程序swiper实现 句子控app首页滑动卡片

    微信小程序swiper实现 句子控app首页滑动卡片 引言:最近看到句子控APP首页的效果很清新,可是发现他的微信小程序端没有实现这个功能,我看了一下难度不大,于是尝试着去实现. 实现效果如下: 1. ...