Loading

nodejs+express+mongodb实现登录注册

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一下,否则可能依赖添加不完全。

posted @ 2020-12-27 11:39  iterationjia  阅读(480)  评论(0)    收藏  举报