分享node.js实现简单登录注册的具体代码


Posted in NodeJs onApril 26, 2022

1、首先需要一个sever模块用于引入路由,引入连接数据库的模块,监听服务器
2、要有model层,里面写数据库连接模块和数据库的各种model(表),并导出model对象
3、工具类utils,里面存放一些功能的模块,并且封装后导出 ,例如发送验证码的功能
4、写路由,需要对数据库操作就使用导出的model对象,需要功能模块就使用导出的功能对象
随后返回这个路由,在sever里引入
5、生成api文档

sever模块

//实现登录注册,要先自己写路由放在本地的服务器上
const express=require('express');
//登录注册需要连接到服务器,连接的逻辑单独为一个db包,这里面放着和数据库有关的,比如说数据库的表,数据库的连接
//这里只需要引入连接上述包的连接模块即实现连接
const db=require('./db/connect');

//实例化express模块,这里的实例化对象就是用来操作路由啊使用中间件之类的,都是它
const app=express();

//引入解析请求体的中间件模块,方便路由里可以直接使用数据
const bodyparser=require('body-parser');
//使用这里面的解析请求体的方法
//这里use里面使用的是中间件模块的方法,所以里面是点---------
app.use(bodyparser.urlencoded({extended:false}))
app.use(bodyparser.json())


//下面就是连接路由,先去写下路由,之后在那里导出,这里就可以连接到了
//router里面存放的是全部的不同的路由
//在使用路由之前需要引入能解析请求体的中间件
//引入路由
const userRouter=require('./router/userRouter')
app.use('/user',userRouter);


//开启端口号为3000的本地服务器
app.listen(3000,()=>{
    console.log("服务器已开启");


})

数据库model包

1.根目录下的数据库连接

//这个模块不需要导出什么,其他地方引入这个模块就自动执行里面的代码,不需要返回的数据进行下一步操作
//因此不需要导出
const mongoose=require('mongoose');
mongoose.connect('mongodb://localhost/first');//连接到哪一个数据库
let db=mongoose.connection;//数据库连接后的对象,以便于后续对连接过程的监听
db.on("error",console.error.bind(console,"连接异常"));
db.once("open",()=>{
    console.log("连接成功");
})

2.model模块(表)

//对数据库操作,需要mongoose模块
const mongoose=require('mongoose');

//由于前面已经连接到数据库了,这里就可以直接创建schema对象了
const userSchema=mongoose.Schema({
    us:{type:String,required:true},
    ps:{type:String,required:true},
    age:Number,
    sex:{type:Number,default:0}
})

//这里需要对上面创建的表头(字段)集合转化为模型,即集合为一张表
//并返回一个对象,方便后续对表的操作,这里的对象需要导出,方便在其他模块使用
//这里导出,是为了在路由里使用这个对象对数据库进行操作
const User=mongoose.model("users",userSchema);//使用model方法转化,第一个参数是表名,第二个参数是需要转化的模型
module.exports=User;

工具类utils

//utils是工具类的包,那么发送邮件的程序算是一个工具
//这里将发送的方法封装并导出
const nodemailer=require('nodemailer');

//使用node方法创建发送的对象,接下来发送的方法肯定是该对象操作的
//创建发送对象基本都是固定格式
let transporter=nodemailer.createTransport({
    host:"smtp.qq.com",//发送方使用的邮箱
    port:465,//端口号,可以在lib/well-known/service.json下找到这些信息
    secure:true,
    auth:{
        user:"1507337624@qq.com",
        pass:""   //这里不是邮箱密码,而是邮箱开始第三方发送时给的验证码
    }
})

//这里将发送的方法封装,因为只需要导出这个方法,其他并不需要导出

function send(mail,code){
    //邮件信息
    let mailContent={
        from:'<1507337624@qq.com>',
        to:mail,
       subject:"验证码 ",
       text:`您的验证码是$[code],有效期五分钟`
    }
    //这里的发送是异步的,发送成功与否只有回调函数里才知道,那么总不能发送成功后的代码都写在这个工具里吧
    //这只是个工具类,发送成功和失败返回就行,谁用就谁处理
    //那么返回回调函数的失败或者成功就要promise对象了,这里直接给发送的结果返回一个promise对象
    return new Promise((resolve,reject)=>{
        transporter.sendMail(mailContent,(err,data)=>{
            //错误优先,err默认为null,另一个参数data包含了发送的一系列信息,状态,数据之类
            if(err){
                //执行reject就意味着错误,promise就会走catch
                reject()
            }else{
                resolve()
            }
        })
    })
}
module.exports={send}//这里返回的是一个对象,里面有一个属性是send,而不是直接返回send方法本身,其实两者都可以,但是规范上来说更多的是这个

核心路由router

这里写接收并且处理请求的具体方法

//创建一个路由就要先实例化express下创建路由的方法
const express=require('express');
const router=express.Router();//注意这里的router是方法,需要括号
//登录注册等需要对数据库进行操作,这里需要对应的model,先去创建一个model
//创建好了,可以引入了
const User=require("../db/model/userModel");

//注册还需要邮箱验证,那么邮箱验证是一个单独的功能,也就是需要实现的工具类的功能
//所以需要单独一个包存放工具类功能,之后需要的时候引入就可以了,这里先去写
//好了写完了,下面可以导入了
const Mail=require('../utils/mail');
//那么问题来了,导入之后在哪里调用,发送邮箱验证码也是一个请求吧
//既然是请求就应该有对应的接口,因为毕竟是在用户注册上请求发送验证码,所以归在用户路由下

//创建一个全局变量用于保存验证码信息,和注册的邮箱是对应的,因此这个变量是对象,注册的邮箱作为属性
const mailCodes={}

//接下来就可以写路由的接口了
//
//注册接口,生成 接口文档
/**
 * @api {post} /user/register 用户注册
 * @apiName 用户注册
 * @apiGroup User
 *
 * @apiParam {String} us 用户名
 * @apiParam {String} ps 密码
 * @apiParam {String} mailCode 验证码
 *
 * @apiSuccess {String} firstname Firstname of the User.
 * @apiSuccess {String} lastname  Lastname of the User.
 */
//这里需要对post请求的body分析,需要body-parser中间件,
//但是这里只返回给serve路由 ,因此要在server层引入
router.post('/register',(req,res)=>{
    let{us,ps,mailCode}=req.body;

    //先判断us和ps还有验证码是否都输入了,如果没输入完成直接就终止执行
    if(!us||!ps||!mailCode)return res.send({err:-1,msg:"参数错误"})

    //将保存的验证码对应的us属性的值与传来的验证码比较,不对的话直接就终止了,不需要再往下进行了
    if(mailCodes[us]!=mailCode)return res.send({err:-4,msg:"验证码不正确"})

    //接下来需要判断用户名是否存在,不存在的话就可以注册
    User.find({us})
        .then((data)=>{
            //只要去找了,就会返回数据,没找到返回空,否则返回找到的数据
            if (data.length==0){
                //没有的话就可以注册了,那么下一步操作也是需要返回promise对象,方便链式调用
                //这里涉及到对数据库的操作,需要引入数据库的model,在顶部引入
               return  User.insertMany({us,ps})
            }else{
                //如果存在的话就不能注册,那么就需要返回错误信息
                return res.send({err:-3,msg:"该用户名已存在"})
            }
        })
        //之前说过对数据库的操作默认返回一个promise对象,可以直接then,catch
        //复习一下对数据库操作返回的promise是内部定义的,then里面回调参数是data,即查询或者插入的数据之类
        //而catch里面的参数err就是错误信息
        .then(()=>{
            //这里的res.send是像前台返回的信息,前面路由创建的学习说过了
            res.send({err:0,msg:"注册ok"})
        })
        //无论是几个链式调用,只要有异常都会来到这里
        .catch((err)=>{
            //这里的错误不是注册过程中重复不能注册的错误,这里应该是数据库连接异常的错误这类
            res.send({err:-1,msg:"内部错误"})
        })

})

//登录接口,接口文档
/**
 * @api {post} /user/login  用户登录
 * @apiName 用户登录
 * @apiGroup User
 *
 * @apiParam {String} us 用户名
 * @apiParam {String} ps 密码
 *
 * @apiSuccess {String} firstname Firstname of the User.
 * @apiSuccess {String} lastname  Lastname of the User.
 */
router.post("/login",(req,res)=>{
    let{us,ps}=req.body;

    //先判断us和ps还有验证码是否都输入了,如果没输入完成直接就终止执行
    if(!us||!ps)return res.send({err:-1,msg:"参数错误"})


        //下面的find直接就在数据库里寻找了,找到了返回数据,否则返回空(都是一个数组)
        User.find({us,ps})
        .then((data)=>{
            //如果找到了,则data的长度大于0,反之是没找到
            if(data.length>0){
                res.send({err:0,msg:"登录 OK"})
            }else{
                res.send({err:-1,msg:"用户名或密码错误"})
            }
        })
        .catch((err)=>{
            res.send({err:-2,msg:"内部错误"})
        })

})

//接口文档
/**
 * @api {post} /user/getCode  获取验证码
 * @apiName 获取验证码
 * @apiGroup User
 *
 * @apiParam {String} us 用户名
 *
 * @apiSuccess {String} firstname Firstname of the User.
 * @apiSuccess {String} lastname  Lastname of the User.
 */
//为什么会在这里写一个发送邮箱验证码的接口,它原本是一个方法,
// 但是请求后台发送一个验证码,并且传入需要发送的邮箱,这本身就是一个完整的请求
//想一下,我在页面上注册的时候,输入邮箱后点击发送验证码,这不是一个请求吗,那不就需要一个接口吗
router.post('/getCode',(req,res)=>{
    let {us}=req.body;//从请求体中找到需要发送的地址
    //这里利用随机函数生成随机数
    //强转为整数,这里之所以用变量保存起来,是因为下面需要将验证码和发送的对象一起保存
    //发送对象作为属性,验证码为值,因为后续需要比较验证码,所以需要一个全局变量来保存,去上面创建
    let code=parseInt(Math.random()*10000)
    Mail.send(us,code)
        .then(()=>{
            //发送成功要返回信息,并且保存验证码
            //验证码一定在发送成功后保存,否则随便输入一个不管发送成功还是失败都保存的话会大量占用空间
            res.send({err:0,msg:"验证码发送成功"})
            mailCodes[us]=code;//将邮箱和验证码一一对应保存起来,方便其他接口的比较
        })
        .catch(()=>{
            res.send({err:-3,msg:"发送失败,请检查邮箱是否正确或网络连接"})
        })

})
//路由写完了,现在可以把该数据库返回到操作层了
module.exports=router;
NodeJs 相关文章推荐
利用NodeJS和PhantomJS抓取网站页面信息以及网站截图
Nov 18 NodeJs
基于NodeJS的前后端分离的思考与实践(五)多终端适配
Sep 26 NodeJs
PHP和NodeJs开发的应用如何共用Session
Apr 16 NodeJs
windows下安装nodejs及框架express
Aug 07 NodeJs
使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
Aug 21 NodeJs
Nodejs进阶:核心模块net入门学习与实例讲解
Nov 21 NodeJs
详解nodejs中exports和module.exports的区别
Feb 17 NodeJs
Nodejs多站点切换Htpps协议详解及简单实例
Feb 23 NodeJs
nodejs入门教程一:概念与用法简介
Apr 24 NodeJs
nodeJS微信分享
Dec 20 NodeJs
nodejs简单读写excel内容的方法示例
Mar 16 NodeJs
NodeJs实现简易WEB上传下载服务器
Aug 10 NodeJs
分享五个Node.js开发的优秀实践 
Apr 07 #NodeJs
Node.js实现爬取网站图片的示例代码
NodeJs使用webpack打包项目的方法详解
Feb 28 #NodeJs
node快速搭建后台的实现步骤
nodejs利用readline提示输入内容实例代码
详解NodeJS模块化
NodeJs内存占用过高的排查实战记录
You might like
为查询结果建立向后/向前按钮
2006/10/09 PHP
php中利用explode函数分割字符串到数组
2014/02/08 PHP
windows8.1下Apache+Php+MySQL配置步骤
2015/10/30 PHP
jQuery 选择表格(table)里的行和列及改变简单样式
2012/12/15 Javascript
javascript时间自动刷新实现原理与步骤
2013/01/06 Javascript
jQuery div层的放大与缩小简单实现代码
2013/03/28 Javascript
JavaScript静态类型检查工具FLOW简介
2015/01/06 Javascript
JS组件Bootstrap Table表格多行拖拽效果实现代码
2015/12/08 Javascript
JavaScript jquery及AJAX小结
2016/01/24 Javascript
jQuery form插件的使用之处理server返回的JSON, XML,HTML数据
2016/01/26 Javascript
jQuery Easyui快速入门教程
2016/08/21 Javascript
vuejs2.0实现分页组件使用$emit进行事件监听数据传递的方法
2017/02/22 Javascript
Angular.Js中ng-include指令的使用与实现
2017/05/07 Javascript
微信小程序开发之animation循环动画实现的让云朵飘效果
2017/07/14 Javascript
使用vue-aplayer插件时出现的问题的解决
2018/03/02 Javascript
vue实现动态添加数据滚动条自动滚动到底部的示例代码
2018/07/06 Javascript
vue实现一个炫酷的日历组件
2018/10/08 Javascript
基于NodeJS开发钉钉回调接口实现AES-CBC加解密
2020/08/20 NodeJs
[12:36]《DOTA2》国服注册与激活指南全攻略
2013/04/28 DOTA
Python linecache.getline()读取文件中特定一行的脚本
2008/09/06 Python
解决pandas中读取中文名称的csv文件报错的问题
2018/07/04 Python
使用PyCharm创建Django项目及基本配置详解
2018/10/24 Python
Python计算库numpy进行方差/标准方差/样本标准方差/协方差的计算
2018/12/28 Python
python 扩展print打印文件路径和当前时间信息的实例代码
2019/10/11 Python
Python文件操作模拟用户登陆代码实例
2020/06/09 Python
python 提高开发效率的5个小技巧
2020/10/19 Python
用html5实现语音搜索框的方法
2014/03/18 HTML / CSS
如何利用input事件来监听移动端的输入
2016/04/15 HTML / CSS
BRASTY捷克:购买香水、化妆品、手袋和手表
2017/07/12 全球购物
数以千计的折扣工业产品:ESE Direct
2018/05/20 全球购物
北京奥运会口号
2014/06/21 职场文书
四风问题班子对照检查材料
2014/09/27 职场文书
2014年小学教学工作总结
2014/11/13 职场文书
地心历险记观后感
2015/06/15 职场文书
oracle覆盖导入dmp文件的2种方法
2021/05/21 Oracle
联想win10摄像头打不开怎么办?win10笔记本摄像头打不开解决办法
2022/04/08 数码科技