分享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实现PHP的print_r函数代码
Mar 14 NodeJs
Nodejs实现的一个简单udp广播服务器、客户端
Sep 25 NodeJs
nodejs教程之入门
Nov 21 NodeJs
windows下安装nodejs及框架express
Aug 07 NodeJs
nodejs利用http模块实现银行卡所属银行查询和骚扰电话验证示例
Dec 30 NodeJs
nodejs的压缩文件模块archiver用法示例
Jan 18 NodeJs
nodejs结合Socket.IO实现的即时通讯功能详解
Jan 12 NodeJs
nodejs取得当前执行路径的方法
May 13 NodeJs
nodejs中express入门和基础知识点学习
Sep 13 NodeJs
NodeJs 文件系统操作模块fs使用方法详解
Nov 26 NodeJs
NodeJs操作MongoDB教程之分页功能以及常见问题
Apr 09 NodeJs
nodejs各种姿势断点调试的方法
Jun 18 NodeJs
分享五个Node.js开发的优秀实践 
Apr 07 #NodeJs
Node.js实现爬取网站图片的示例代码
NodeJs使用webpack打包项目的方法详解
Feb 28 #NodeJs
node快速搭建后台的实现步骤
nodejs利用readline提示输入内容实例代码
详解NodeJS模块化
NodeJs内存占用过高的排查实战记录
You might like
php实现粘贴截图并完成上传功能
2015/05/17 PHP
摘自织梦CMS中的图片处理类
2015/08/08 PHP
PHP调用接口用post方法传送json数据的实例
2018/05/31 PHP
ko knockoutjs动态属性绑定技巧应用
2012/11/14 Javascript
JavaScript模拟实现继承的方法
2015/03/30 Javascript
jquery 多个radio的click事件实例
2016/12/03 Javascript
canvas学习之API整理笔记(一)
2016/12/29 Javascript
原生JS轮播图插件
2017/02/09 Javascript
ES6入门教程之let和const命令详解
2017/05/17 Javascript
vue实现移动端触屏拖拽功能
2020/08/21 Javascript
vue 获取元素额外生成的data-v-xxx操作
2020/09/09 Javascript
在vue中动态修改css其中一个属性值操作
2020/12/07 Vue.js
[02:45]DOTA2英雄敌法师基础教程
2013/11/25 DOTA
python 简易计算器程序,代码就几行
2009/08/29 Python
为Python程序添加图形化界面的教程
2015/04/29 Python
Python中基础的socket编程实战攻略
2016/06/01 Python
Python3连接SQLServer、Oracle、MySql的方法
2018/06/28 Python
python 遍历目录(包括子目录)下所有文件的实例
2018/07/11 Python
python读取文件名并改名字的实例
2019/01/07 Python
Django 缓存配置Redis使用详解
2019/07/23 Python
Python安装及Pycharm安装使用教程图解
2019/09/20 Python
python matplotlib 画dataframe的时间序列图实例
2019/11/20 Python
Python dict的常用方法示例代码
2020/06/23 Python
python+pygame实现坦克大战小游戏的示例代码(可以自定义子弹速度)
2020/08/11 Python
简单掌握CSS3将文字描边及填充文字颜色的方法
2016/03/07 HTML / CSS
html5 Canvas画图教程(7)—canvas里画曲线之quadraticCurveTo方法
2013/01/09 HTML / CSS
美国电视购物HSN官网:HSN
2016/09/07 全球购物
英国第一独立滑雪板商店:The Snowboard Asylum
2020/01/16 全球购物
美国领先的机场停车聚合商:Airport Parking Reservations
2020/02/28 全球购物
儿科主治医生个人求职信
2013/09/23 职场文书
《蓝色的树叶》教学反思
2014/02/24 职场文书
弄虚作假心得体会
2014/09/10 职场文书
办护照工作证明
2014/10/01 职场文书
公司2014年度工作总结
2014/12/10 职场文书
jquery插件实现图片悬浮
2021/04/16 jQuery
pycharm安装深度学习pytorch的d2l包失败问题解决
2022/03/25 Python