node.js實現(xiàn)簡單登錄注冊功能
本文實例為大家分享了node.js實現(xiàn)簡單登錄注冊的具體代碼,供大家參考,具體內(nèi)容如下
1、首先需要一個sever模塊用于引入路由,引入連接數(shù)據(jù)庫的模塊,監(jiān)聽服務器
2、要有model層,里面寫數(shù)據(jù)庫連接模塊和數(shù)據(jù)庫的各種model(表),并導出model對象
3、工具類utils,里面存放一些功能的模塊,并且封裝后導出 ,例如發(fā)送驗證碼的功能
4、寫路由,需要對數(shù)據(jù)庫操作就使用導出的model對象,需要功能模塊就使用導出的功能對象
隨后返回這個路由,在sever里引入
5、生成api文檔
sever模塊
//實現(xiàn)登錄注冊,要先自己寫路由放在本地的服務器上
const express=require('express');
//登錄注冊需要連接到服務器,連接的邏輯單獨為一個db包,這里面放著和數(shù)據(jù)庫有關(guān)的,比如說數(shù)據(jù)庫的表,數(shù)據(jù)庫的連接
//這里只需要引入連接上述包的連接模塊即實現(xiàn)連接
const db=require('./db/connect');
//實例化express模塊,這里的實例化對象就是用來操作路由啊使用中間件之類的,都是它
const app=express();
//引入解析請求體的中間件模塊,方便路由里可以直接使用數(shù)據(jù)
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("服務器已開啟");
})數(shù)據(jù)庫model包
1.根目錄下的數(shù)據(jù)庫連接
//這個模塊不需要導出什么,其他地方引入這個模塊就自動執(zhí)行里面的代碼,不需要返回的數(shù)據(jù)進行下一步操作
//因此不需要導出
const mongoose=require('mongoose');
mongoose.connect('mongodb://localhost/first');//連接到哪一個數(shù)據(jù)庫
let db=mongoose.connection;//數(shù)據(jù)庫連接后的對象,以便于后續(xù)對連接過程的監(jiān)聽
db.on("error",console.error.bind(console,"連接異常"));
db.once("open",()=>{
? ? console.log("連接成功");
})2.model模塊(表)
//對數(shù)據(jù)庫操作,需要mongoose模塊
const mongoose=require('mongoose');
//由于前面已經(jīng)連接到數(shù)據(jù)庫了,這里就可以直接創(chuàng)建schema對象了
const userSchema=mongoose.Schema({
? ? us:{type:String,required:true},
? ? ps:{type:String,required:true},
? ? age:Number,
? ? sex:{type:Number,default:0}
})
//這里需要對上面創(chuàng)建的表頭(字段)集合轉(zhuǎn)化為模型,即集合為一張表
//并返回一個對象,方便后續(xù)對表的操作,這里的對象需要導出,方便在其他模塊使用
//這里導出,是為了在路由里使用這個對象對數(shù)據(jù)庫進行操作
const User=mongoose.model("users",userSchema);//使用model方法轉(zhuǎn)化,第一個參數(shù)是表名,第二個參數(shù)是需要轉(zhuǎn)化的模型
module.exports=User;工具類utils
//utils是工具類的包,那么發(fā)送郵件的程序算是一個工具
//這里將發(fā)送的方法封裝并導出
const nodemailer=require('nodemailer');
//使用node方法創(chuàng)建發(fā)送的對象,接下來發(fā)送的方法肯定是該對象操作的
//創(chuàng)建發(fā)送對象基本都是固定格式
let transporter=nodemailer.createTransport({
? ? host:"smtp.qq.com",//發(fā)送方使用的郵箱
? ? port:465,//端口號,可以在lib/well-known/service.json下找到這些信息
? ? secure:true,
? ? auth:{
? ? ? ? user:"1507337624@qq.com",
? ? ? ? pass:"" ? //這里不是郵箱密碼,而是郵箱開始第三方發(fā)送時給的驗證碼
? ? }
})
//這里將發(fā)送的方法封裝,因為只需要導出這個方法,其他并不需要導出
function send(mail,code){
? ? //郵件信息
? ? let mailContent={
? ? ? ? from:'<1507337624@qq.com>',
? ? ? ? to:mail,
? ? ? ?subject:"驗證碼 ",
? ? ? ?text:`您的驗證碼是$[code],有效期五分鐘`
? ? }
? ? //這里的發(fā)送是異步的,發(fā)送成功與否只有回調(diào)函數(shù)里才知道,那么總不能發(fā)送成功后的代碼都寫在這個工具里吧
? ? //這只是個工具類,發(fā)送成功和失敗返回就行,誰用就誰處理
? ? //那么返回回調(diào)函數(shù)的失敗或者成功就要promise對象了,這里直接給發(fā)送的結(jié)果返回一個promise對象
? ? return new Promise((resolve,reject)=>{
? ? ? ? transporter.sendMail(mailContent,(err,data)=>{
? ? ? ? ? ? //錯誤優(yōu)先,err默認為null,另一個參數(shù)data包含了發(fā)送的一系列信息,狀態(tài),數(shù)據(jù)之類
? ? ? ? ? ? if(err){
? ? ? ? ? ? ? ? //執(zhí)行reject就意味著錯誤,promise就會走catch
? ? ? ? ? ? ? ? reject()
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? resolve()
? ? ? ? ? ? }
? ? ? ? })
? ? })
}
module.exports={send}//這里返回的是一個對象,里面有一個屬性是send,而不是直接返回send方法本身,其實兩者都可以,但是規(guī)范上來說更多的是這個核心路由router
這里寫接收并且處理請求的具體方法
//創(chuàng)建一個路由就要先實例化express下創(chuàng)建路由的方法
const express=require('express');
const router=express.Router();//注意這里的router是方法,需要括號
//登錄注冊等需要對數(shù)據(jù)庫進行操作,這里需要對應的model,先去創(chuàng)建一個model
//創(chuàng)建好了,可以引入了
const User=require("../db/model/userModel");
//注冊還需要郵箱驗證,那么郵箱驗證是一個單獨的功能,也就是需要實現(xiàn)的工具類的功能
//所以需要單獨一個包存放工具類功能,之后需要的時候引入就可以了,這里先去寫
//好了寫完了,下面可以導入了
const Mail=require('../utils/mail');
//那么問題來了,導入之后在哪里調(diào)用,發(fā)送郵箱驗證碼也是一個請求吧
//既然是請求就應該有對應的接口,因為畢竟是在用戶注冊上請求發(fā)送驗證碼,所以歸在用戶路由下
//創(chuàng)建一個全局變量用于保存驗證碼信息,和注冊的郵箱是對應的,因此這個變量是對象,注冊的郵箱作為屬性
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還有驗證碼是否都輸入了,如果沒輸入完成直接就終止執(zhí)行
? ? if(!us||!ps||!mailCode)return res.send({err:-1,msg:"參數(shù)錯誤"})
? ? //將保存的驗證碼對應的us屬性的值與傳來的驗證碼比較,不對的話直接就終止了,不需要再往下進行了
? ? if(mailCodes[us]!=mailCode)return res.send({err:-4,msg:"驗證碼不正確"})
? ? //接下來需要判斷用戶名是否存在,不存在的話就可以注冊
? ? User.find({us})
? ? ? ? .then((data)=>{
? ? ? ? ? ? //只要去找了,就會返回數(shù)據(jù),沒找到返回空,否則返回找到的數(shù)據(jù)
? ? ? ? ? ? if (data.length==0){
? ? ? ? ? ? ? ? //沒有的話就可以注冊了,那么下一步操作也是需要返回promise對象,方便鏈式調(diào)用
? ? ? ? ? ? ? ? //這里涉及到對數(shù)據(jù)庫的操作,需要引入數(shù)據(jù)庫的model,在頂部引入
? ? ? ? ? ? ? ?return ?User.insertMany({us,ps})
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? //如果存在的話就不能注冊,那么就需要返回錯誤信息
? ? ? ? ? ? ? ? return res.send({err:-3,msg:"該用戶名已存在"})
? ? ? ? ? ? }
? ? ? ? })
? ? ? ? //之前說過對數(shù)據(jù)庫的操作默認返回一個promise對象,可以直接then,catch
? ? ? ? //復習一下對數(shù)據(jù)庫操作返回的promise是內(nèi)部定義的,then里面回調(diào)參數(shù)是data,即查詢或者插入的數(shù)據(jù)之類
? ? ? ? //而catch里面的參數(shù)err就是錯誤信息
? ? ? ? .then(()=>{
? ? ? ? ? ? //這里的res.send是像前臺返回的信息,前面路由創(chuàng)建的學習說過了
? ? ? ? ? ? res.send({err:0,msg:"注冊ok"})
? ? ? ? })
? ? ? ? //無論是幾個鏈式調(diào)用,只要有異常都會來到這里
? ? ? ? .catch((err)=>{
? ? ? ? ? ? //這里的錯誤不是注冊過程中重復不能注冊的錯誤,這里應該是數(shù)據(jù)庫連接異常的錯誤這類
? ? ? ? ? ? res.send({err:-1,msg:"內(nèi)部錯誤"})
? ? ? ? })
})
//登錄接口,接口文檔
/**
?* @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還有驗證碼是否都輸入了,如果沒輸入完成直接就終止執(zhí)行
? ? if(!us||!ps)return res.send({err:-1,msg:"參數(shù)錯誤"})
? ? ? ? //下面的find直接就在數(shù)據(jù)庫里尋找了,找到了返回數(shù)據(jù),否則返回空(都是一個數(shù)組)
? ? ? ? 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:"內(nèi)部錯誤"})
? ? ? ? })
})
//接口文檔
/**
?* @api {post} /user/getCode ?獲取驗證碼
?* @apiName 獲取驗證碼
?* @apiGroup User
?*
?* @apiParam {String} us 用戶名
?*
?* @apiSuccess {String} firstname Firstname of the User.
?* @apiSuccess {String} lastname ?Lastname of the User.
?*/
//為什么會在這里寫一個發(fā)送郵箱驗證碼的接口,它原本是一個方法,
// 但是請求后臺發(fā)送一個驗證碼,并且傳入需要發(fā)送的郵箱,這本身就是一個完整的請求
//想一下,我在頁面上注冊的時候,輸入郵箱后點擊發(fā)送驗證碼,這不是一個請求嗎,那不就需要一個接口嗎
router.post('/getCode',(req,res)=>{
? ? let {us}=req.body;//從請求體中找到需要發(fā)送的地址
? ? //這里利用隨機函數(shù)生成隨機數(shù)
? ? //強轉(zhuǎn)為整數(shù),這里之所以用變量保存起來,是因為下面需要將驗證碼和發(fā)送的對象一起保存
? ? //發(fā)送對象作為屬性,驗證碼為值,因為后續(xù)需要比較驗證碼,所以需要一個全局變量來保存,去上面創(chuàng)建
? ? let code=parseInt(Math.random()*10000)
? ? Mail.send(us,code)
? ? ? ? .then(()=>{
? ? ? ? ? ? //發(fā)送成功要返回信息,并且保存驗證碼
? ? ? ? ? ? //驗證碼一定在發(fā)送成功后保存,否則隨便輸入一個不管發(fā)送成功還是失敗都保存的話會大量占用空間
? ? ? ? ? ? res.send({err:0,msg:"驗證碼發(fā)送成功"})
? ? ? ? ? ? mailCodes[us]=code;//將郵箱和驗證碼一一對應保存起來,方便其他接口的比較
? ? ? ? })
? ? ? ? .catch(()=>{
? ? ? ? ? ? res.send({err:-3,msg:"發(fā)送失敗,請檢查郵箱是否正確或網(wǎng)絡連接"})
? ? ? ? })
})
//路由寫完了,現(xiàn)在可以把該數(shù)據(jù)庫返回到操作層了
module.exports=router;以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
no-vnc和node.js實現(xiàn)web遠程桌面的完整步驟
這篇文章主要給大家介紹了關(guān)于no-vnc和node.js實現(xiàn)web遠程桌面的完整步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-08-08
使用cluster 將自己的Node服務器擴展為多線程服務器
nodejs在v0.6.x之后 增加了一個模塊 cluster 用于實現(xiàn)多進程,利用child_process模塊來創(chuàng)建和管理進程,增加程序在多核CPU機器上的性能表現(xiàn)。本文將介紹利用cluster模塊創(chuàng)建的多線程的問題。2014-11-11
node.js支持多用戶web終端實現(xiàn)及安全方案
這篇文章主要介紹了node.js支持多用戶web終端實現(xiàn)方案以及web終端安全性保證的解決方法,一起學習參考下。2017-11-11
使用nodejs搭建一個簡易HTTP服務的實現(xiàn)示例
本文主要介紹了使用nodejs搭建一個簡易HTTP服務的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-05-05
node?NPM庫增強版globby?Promise使用學習
這篇文章主要為大家介紹了node?NPM庫增強版globby?Promise使用學習,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07

