分享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教程 安装express及配置app.js文件的详细步骤
May 11 NodeJs
nodejs命令行参数处理模块commander使用实例
Sep 17 NodeJs
nodejs中实现阻塞实例
Mar 24 NodeJs
Windows 系统下设置Nodejs NPM全局路径
Apr 26 NodeJs
nodeJS删除文件方法示例
Dec 25 NodeJs
nodejs中全局变量的实例解析
Mar 07 NodeJs
浅析 NodeJs 的几种文件路径
Jun 07 NodeJs
Nodejs模块的调用操作实例分析
Dec 25 NodeJs
nodeJS进程管理器pm2的使用
Jan 09 NodeJs
nodejs实现用户登录路由功能
May 22 NodeJs
linux 下以二进制的方式安装 nodejs
Feb 12 NodeJs
NodeJS多种创建WebSocket监听的方式(三种)
Jun 04 NodeJs
分享五个Node.js开发的优秀实践 
Apr 07 #NodeJs
Node.js实现爬取网站图片的示例代码
NodeJs使用webpack打包项目的方法详解
Feb 28 #NodeJs
node快速搭建后台的实现步骤
nodejs利用readline提示输入内容实例代码
详解NodeJS模块化
NodeJs内存占用过高的排查实战记录
You might like
php中的curl_multi系列函数使用例子
2014/07/29 PHP
jquery+php+ajax显示上传进度的多图片上传并生成缩略图代码
2014/10/15 PHP
php数组操作之键名比较与差集、交集赋值的方法
2014/11/10 PHP
laravel容器延迟加载以及auth扩展详解
2015/03/02 PHP
PHP面向对象五大原则之里氏替换原则(LSP)详解
2018/04/08 PHP
JQuery之拖拽插件实现代码
2011/04/14 Javascript
ASP.NET中AJAX 调用实例代码
2012/05/03 Javascript
如何使用json在前后台进行数据传输实例介绍
2013/04/11 Javascript
jquery对dom的操作常用方法整理
2013/06/25 Javascript
jQuery的attr与prop使用介绍
2013/10/10 Javascript
node.js中的path.resolve方法使用说明
2014/12/08 Javascript
js实现文件上传表单域美化特效
2015/11/02 Javascript
jQuery实现textarea自动增长宽高的方法
2015/12/18 Javascript
基于JavaScript实现图片点击弹出窗口而不是保存
2016/02/06 Javascript
基于JS实现限时抢购倒计时间表代码
2017/05/09 Javascript
js实现控制文件拖拽并获取拖拽内容功能
2018/02/17 Javascript
详解浏览器缓存和webpack缓存配置
2018/07/06 Javascript
jQuery插件实现非常实用的tab栏切换功能【案例】
2019/02/18 jQuery
Node.js 实现简单的无侵入式缓存框架的方法
2019/07/21 Javascript
JS Thunk 函数的含义和用法实例总结
2020/04/08 Javascript
[03:02]安得倚天剑,跨海斩长鲸——中国军团出征DOTA2国际邀请赛
2018/08/14 DOTA
Python编程中字符串和列表的基本知识讲解
2015/10/14 Python
让Python更加充分的使用Sqlite3
2017/12/11 Python
Python实现调用另一个路径下py文件中的函数方法总结
2018/06/07 Python
python conda操作方法
2019/09/11 Python
Python Tkinter模块 GUI 可视化实例
2019/11/20 Python
Python基于pygame实现单机版五子棋对战
2019/12/26 Python
python3.6使用SMTP协议发送邮件
2020/05/20 Python
python 解决mysql where in 对列表(list,,array)问题
2020/06/06 Python
英国亚马逊官方网站:Amazon.co.uk
2019/08/09 全球购物
英国鲜花递送:Blossoming Gifts
2020/07/10 全球购物
中软国际Java程序员笔试题
2014/07/19 面试题
学生会主席演讲稿
2014/04/25 职场文书
国际贸易专业自荐信
2014/06/10 职场文书
小学安全教育月活动总结
2014/07/07 职场文书
总结Python连接CS2000的详细步骤
2021/06/23 Python