分享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的require模块(文件模块/核心模块)及路径介绍
Jan 14 NodeJs
利用NodeJS的子进程(child_process)调用系统命令的方法分享
Jun 05 NodeJs
NodeJS与Mysql的交互示例代码
Aug 18 NodeJs
使用upstart把nodejs应用封装为系统服务实例
Jun 01 NodeJs
NodeJS学习笔记之网络编程
Aug 03 NodeJs
详解nodejs 文本操作模块-fs模块(三)
Dec 22 NodeJs
nodeJs链接Mysql做增删改查的简单操作
Feb 04 NodeJs
Express与NodeJs创建服务器的两种方法
Feb 06 NodeJs
nodejs个人博客开发第三步 载入页面
Apr 12 NodeJs
NodeJS实现同步的方法
Mar 02 NodeJs
nodejs+express最简易的连接数据库的方法
Dec 23 NodeJs
分享五个Node.js开发的优秀实践 
Apr 07 #NodeJs
Node.js实现爬取网站图片的示例代码
NodeJs使用webpack打包项目的方法详解
Feb 28 #NodeJs
node快速搭建后台的实现步骤
nodejs利用readline提示输入内容实例代码
详解NodeJS模块化
NodeJs内存占用过高的排查实战记录
You might like
服务器端解压缩zip的脚本
2006/12/22 PHP
JS实现php的伪分页
2008/05/25 PHP
总结PHP中DateTime的常用方法
2016/08/11 PHP
PHP 使用位运算实现四则运算的代码
2021/03/09 PHP
基于jquery.Jcrop的头像编辑器
2010/03/01 Javascript
兼容IE、FireFox、Chrome等浏览器的xml处理函数js代码
2011/11/30 Javascript
JavaScript自定义事件介绍
2013/08/29 Javascript
js读取cookie方法总结
2014/10/31 Javascript
对比分析json及XML
2014/11/28 Javascript
原生JS实现响应式瀑布流布局
2015/04/02 Javascript
jQuery自定义滚动条完整实例
2016/01/08 Javascript
jQuery实现的手风琴侧边菜单效果
2017/03/29 jQuery
JavaScript实现移动端页面按手机屏幕分辨率自动缩放的最强代码
2017/08/18 Javascript
Node.js事件的正确使用方法
2019/04/05 Javascript
[01:01:42]Secret vs Optic Supermajor 胜者组 BO3 第二场 6.4
2018/06/05 DOTA
python实现类似ftp传输文件的网络程序示例
2014/04/08 Python
Mac中Python 3环境下安装scrapy的方法教程
2017/10/26 Python
python批量下载抖音视频
2019/06/17 Python
python自动化UI工具发送QQ消息的实例
2019/08/27 Python
Python实现PyPDF2处理PDF文件的方法示例
2019/09/25 Python
Python数据分析pandas模块用法实例详解
2019/11/20 Python
使用python图形模块turtle库绘制樱花、玫瑰、圣诞树代码实例
2020/03/16 Python
Python Opencv轮廓常用操作代码实例解析
2020/09/01 Python
如何给HTML标签中的文本设置修饰线
2019/11/18 HTML / CSS
HTML5基于flash实现播放RTMP协议视频的示例代码
2020/12/04 HTML / CSS
美国体育用品商店:Rally House(NCAA、NFL、MLB、NBA、NHL和MLS)
2018/01/03 全球购物
美团网旗下网上订餐平台:美团外卖
2020/03/05 全球购物
预备党员入党思想汇报
2014/01/04 职场文书
个人简历自我评价
2014/01/06 职场文书
建筑安全员岗位职责
2014/03/13 职场文书
语文教研活动总结
2014/07/02 职场文书
2015年学生会主席工作总结
2015/04/21 职场文书
锦旗赠语
2015/06/23 职场文书
关于践行三严三实的心得体会
2016/01/05 职场文书
党员反邪教心得体会
2016/01/15 职场文书
Windows Server 2016 配置 IIS 的详细步骤
2022/04/28 Servers