当前位置: 首页 > news >正文

【Node.js】项目开发实战(中)

开发用户的注册和登录接口

          • 步骤1,打开MySQL Workbench,打开自己的数据库进入
          • 创建用户信息表
          • 新建 ev_users表
          • 安装并配置mysql模块
          • 安装mysql模块
          • 新建db文件夹下index.js,导入并配置mysql模块
          • 安装bcryptjs对密码进行加密处理
          • 新建/router_handler/user.js中,导入并使用bcrypt.js
      • router_handlerr/user.js用户模块里,书写注册的处理函数
      • 优化res.send()代码
      • 优化表单数据验证
          • 创建schema文件夹,新建user.js
      • 优化后的注册处理函数
      • 开发登录接口
          • 生成JWT的token字符串
          • 配置解析JWT的token字符串的中间件

步骤1,打开MySQL Workbench,打开自己的数据库进入
创建用户信息表
新建 ev_users表
  • id要加AI,设置成自增
    在这里插入图片描述
    在这里插入图片描述
安装并配置mysql模块
安装mysql模块
npm i mysql2
新建db文件夹下index.js,导入并配置mysql模块
// 1.导入mysql2模块
const mysql = require('mysql2')
// 2,建立与MySQL数据库的连接
const db = mysql.createPool({host: "127.0.0.1", //数据库的IP地址user: "root", //登录数据库的账号password: "lusheng123", //登录数据库的密码database: "my_db_01", //指定要操作哪个数据库
})
//3.检测mysql模块是否正常工作 SELECT 1 无作用,只是测试
db.query('SELECT 1',(err, results) => {//err为报错信息if (err) return console.log(err)//res是成功的消息console.log(results) 
}) 
module.exports = db
安装bcryptjs对密码进行加密处理
  • 安装 npm i bcryptjs@2.4.3
  • 优点:加密之后的密码,无法被逆向破解
  • 同一明文密码多次加密,得到到加密效果结果各不相同,保证了安全性
  • 目的,在数据库查看的时候,查看的是加密的密码
新建/router_handler/user.js中,导入并使用bcrypt.js
// 导入密码加密模块
const bcypt = require("bcryptjs")
// 加密用户密码,调用bcypt.hashSync(明文密码,随机盐的长度)方法
userinfo.password=bcypt.hashSync(userinfo.password,10)

router_handlerr/user.js用户模块里,书写注册的处理函数

  • 注意,sql语句要写对,
// 导入数据库操作模块
const db = require("../db/index")
// 导入密码加密模块
const bcypt = require("bcryptjs")
// 注册新用户
exports.reguser = (req, res) => {// 获取客户端提交到服务器的信息,进行校验const userinfo = req.bodyif (!userinfo.username || !userinfo.password) return res.send({status: 0, message: "用户名和密码不合法"})//定义SQL语句,查询用户名是否被占用const sqlStr = "select * from ev_users where username=?"db.query(sqlStr, userinfo.username, (err, result) => {if (err) return res.send({status: 0,message: err.message })// 判断用户名是否被占用if (result.length > 0) return res.send({status: 0, message: "用户名被占用,请更换用户名" })// 加密用户密码,调用bcypt.hashSync(明文密码,随机盐的长度)方法userinfo.password=bcypt.hashSync(userinfo.password,10)// 插入新用户const sql="insert into ev_users set ?"db.query(sql,{username:userinfo.username,password:userinfo.password},(err,results)=>{// 判断是否成功if(err)return res.send({status: 0,message: err.message })// 判断影响行数是否为1if(results.affectedRows!==1)return res.send({status:1,message:"注册用户失败"})return res.send({status: 1,message: "注册成功"})})})
}

优化res.send()代码

  • 在app.js文件里面
  • 注意:封装在路由之前
//响应数据的中间件,上游挂载,下游共享
app.use((req, res, next) => {// status=0是失败,status=1是成功,默认为0res.cc = (err, status = 0) => {res.send({status,// 判断err是错误对象还是字符串message: err instanceof Error ? err.message : err})}next()
})

优化表单数据验证

  • 前端验证为辅,后端验证为主
  • 后端是验证数据合法性验证的最后一个关口
  • 为提高效率,使用第三方库

安装npm i joi包,依赖

  • 定义每条数据的验证规则

安装npm i @escook/express-joi包,

  • 实现自动对表单数据进行验证的功能
创建schema文件夹,新建user.js
  • 存放定义的规则
// 导入joi,定义表单规则
const joi=require("joi")
// 导入express-joi中间件,表单验证模块
const expressJoi=require("@escook/express-joi")const userSchema ={// 校验req.body的数据body:{// 字符串,还必须字符和数字的组合,最小三位,最大12位,必传username:joi.string().alphanum().min(3).max(12).required(),// pattern指定正则表达式password:joi.string().pattern(/"[\s][6,15]$/),//当前规则和paddword规则保持一致repassword:joi.ref('password')},// 校验req.query的数据query:{},// 校验req.params的数据params:{}
}
// 暴露注册的表单验证规则
exports.userSchema=userSchema
  • 在router/user.js中,导入验证表单数据的中间件
//存放每个路由的对应关系
// 导入express
const express = require('express')// 创建路由对象
const router = express.Router()// 导入用户处理函数模块
const userhandler=require('../router_handler/user')// 1.导入验证表单数据的中间件
const expressJoi=require("@escook/express-joi")
// 2.导入需要验证的验证规则对象
const {userSchema}=require('../schema/user')// 3.采用局部中间件方式校·验,校验通过,会把请求转给后面的路由处理函数,校验不通过,终止后续代码的执行,并抛出一个全局的Error错误,进入全局错误中间件中进行处理
// 注册新用户
router.post('/reguser',expressJoi(userSchema),userhandler.reguser)// 登录
router.post('/login', userhandler.login)// 将路由对象共享出去
module.exports = router
  • 在app.js中,捕获表单验证的全局错误
  • 注意:写在路由之后!
//全局错误中间件,捕获表单验证失败的报错
app.use((err, req, res, next) => {if (err instanceof joi.ValidationError) return res.cc(err)res.cc(err)next()
})

优化后的注册处理函数

// 导入数据库操作模块
const db = require("../db/index")
// 导入密码加密模块
const bcypt = require("bcryptjs")
// 注册新用户处理函数
exports.reguser = (req, res) => {// 获取客户端提交到服务器的信息,进行校验const userinfo = req.bodyif (!userinfo.username || !userinfo.password) return res.cc("用户名和密码不合法")//定义SQL语句,查询用户名是否被占用const sqlStr = "select * from ev_users where username=?"db.query(sqlStr, userinfo.username, (err, result) => {if (result.length > 0) return  res.cc("用户名被占用,请更换用户名")// 加密用户密码,调用bcypt.hashSync(明文密码,随机盐的长度)方法userinfo.password=bcypt.hashSync(userinfo.password,10)// 插入新用户const sql="insert into ev_users set ?"db.query(sql,{username:userinfo.username,password:userinfo.password},(err,results)=>{// 判断是否成功if(err)return res.cc(err)// 判断影响行数是否为1if(results.affectedRows!==1)return res.cc("注册用户失败")return res.cc("注册成功",1)})})
}

开发登录接口

生成JWT的token字符串
  • 安装 npm i jsonwebtoken@8.5.1
  • 定义配置文件的秘钥和token有效期
//新建config.js
module.exports={//定义加密解密token的秘钥,随便写jwtSecretKey:'mimakey',// this.token有效期expiresIn:'10h'
}
  • 处理函数中也就是,router_header/user.js文件下引用导入
// 导入JWTtoken模块
const JWT = require("jsonwebtoken")
const config = require("../config")
  • 生成Jwt的token字符串的登录处理函数
// 导入数据库操作模块
const db = require("../db/index")
// 导入密码加密模块
const bcypt = require("bcryptjs")
// 导入JWTtoken模块
const JWT = require("jsonwebtoken")
const config = require("../config")
// 登录
exports.login = (req, res) => {const userinfo = req.bodyconst sql ='select * from ev_users where username=?'db.query(sql,userinfo.username,(err,results)=>{if(err) return res.cc(err);// 执行成功,但查询到的数据不等于1if(results.length!==1){return res.cc('登录失败')}// 验证密码是否和数据库的相同const reppassword= bcypt.compareSync(userinfo.password,results[0].password)if(!reppassword){return res.cc('登录失败,密码不一致')}// 登录成功,生成JWT的token字符串// 通过es6语法,剔除密码和头像const user ={...results[0],password:"",user_pic:""}// 对用户信息进行加密,生成token字符串,参数一是加密对象,参数2是加密秘钥,参数三是token有效期const tokenstr =JWT.sign(user,config.jwtSecretKey,{expiresIn:config.expiresIn})// 响应给客户端,token的bearer后面有空格,别丢res.send({status:1,message:'登录成功',token:'Bearer '+tokenstr})})
}
配置解析JWT的token字符串的中间件
  • 作用:用来解析客户端传过来的token
  • 安装中间件
npm i express-jwt@5.3.3
  • 一定要在app.js中注册路由之前,配置解析token的中间件
// 导入配置文件
const config = require('./config')
// 导入解析token的中间件
const expressJWT = require('express-jwt')
// 使用.unless可以指定哪些接口不需要toke身份验证,演示以api开头的
app.use(expressJWT({secret: config.jwtSecretKey
}).unless({path: [/^\/api\//]
}))
  • 全局错误中间件,捕获解析失败的错误
app.use((err, req, res, next) => {// 捕获token解析失败的错误if (err.name === 'UnauthorizedError') return res.cc('身份验证失败')res.cc(err)next()
})

相关文章:

【Node.js】项目开发实战(中)

开发用户的注册和登录接口步骤1,打开MySQL Workbench,打开自己的数据库进入创建用户信息表新建 ev_users表安装并配置mysql模块安装mysql模块新建db文件夹下index.js,导入并配置mysql模块安装bcryptjs对密码进行加密处理新建/router_handler/user.js中&a…...

记录一次 New Bing 英语陪练

记录一次 New Bing 英语陪练 Now I start to speak english to chat with you . Help me find the mistake in my word and help me improve my english I’m glad you want to practice your English with me. I can help you find the mistakes in your words and help you i…...

【Python】照片居然能变素描?不会画画但是咱会代码

文章目录前言一、准备二、下载预训练模型总结前言 Photo-Sketching 一个能将照片的轮廓识别出来并将其转化为“速写”型图像的开源模块。 比如,这只小狗: 经过模型的转化,会变成卡通版的小狗: 非常秀,这很人工智能…...

已解决正确配置git环境变量

已解决git没有配置环境变量,抛出异常ERROR: Cannot find command ‘git’- do you have ‘git’ installed and in your PATH?,附上正确配置git环境变量的教程 文章目录报错问题报错翻译报错原因解决方法《100天精通Python》专栏推荐白嫖80g Python全栈…...

【逐步剖C】-第十章-自定义类型之结构体、枚举、联合

一、结构体 前言:有关结构体的声明、定义、初始化以及结构体的传参等结构体的基本使用在文章【逐步剖C】-第六章-结构体初阶中已进行了详细的介绍,需要的朋友们可以看看。这里主要讲解的是有关结构体的内存问题。 1. 结构体的内存对齐 (1&…...

Windows Server 2016 中文版、英文版下载 (updated Mar 2023)

Windows Server 2016 Version 1607,2023 年 3 月更新 请访问原文链接:https://sysin.org/blog/windows-server-2016/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 本站将不定期发布官方原版风格月度更…...

Linux 4G 通信实验

目录4G 网络连接简介高新兴ME3630 4G 模块实验ME3630 4G 模块简介ME3630 4G 模块驱动修改ME3630 4G 模块ppp 联网测试前面我们学习了如何在Linux 中使用有线网络或者WIFI,但是使用有线网络或者WIFI 有 很多限制,因为要布线,即使是WIFI 你也得…...

华为OSPF技术详细介绍,保姆级,谁都能看懂(一)

目录 1、简介 2、OSPF基本原理 3、OSPF的特点 4、OSPF区域 5、路由器的类型 6、OSPF5种报文 7、后半部分内容 1、简介 OSPF(Open Shortest Path First,开放最短路径优先)是一个基于链路状态的内部网关协 议。目前针对IPv4协议使用的是OS…...

行人车辆检测与计数系统(Python+YOLOv5深度学习模型+清新界面)

摘要:行人车辆检测与计数系统用于交通路口行人及车辆检测计数,道路人流量、车流量智能监测,方便记录、显示、查看和保存检测结果。本文详细介绍行人车辆检测,在介绍算法原理的同时,给出Python的实现代码、PyQt的UI界面…...

SM3哈希算法的FPGA实现 I

SM3哈希算法的FPGA实现 I SM3哈希算法的FPGA实现 I一、什么是SM3哈希算法?二、SM3哈希算法的具体内容1、填充2、迭代与压缩3、计算拼凑值三、参考文档语言 :verilog 仿真工具: Modelsim EDA工具:quartus II 一、什么是SM3哈希算法…...

【数据结构与算法】线性表--数组

文章目录一、前言二、数组的概念三、数组的操作数组的插入数组的删除四、容器与数组五、问题:为何数组要从0开始编号,而不是1开始呢?六、总结一、前言 常见的数据结构如下图,本文主要讲解数据结构线性表--数组。 二、数组的概念 …...

剑指offer排序专题

剑指offer排序专题 jz3 数组中重复的数字描述 在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组[…...

已解决Cannot open D:\Soft\Python36\Scripts\pip3-script.py

已解决Cannot open D:\Soft\Python36\Scripts\pip3-script.py 文章目录报错问题报错翻译报错原因解决方法1:easy_install 来安装pip解决方法2:本地安装pip《100天精通Python》专栏推荐白嫖80g Python全栈视频报错问题 粉丝群里面的一个小伙伴遇到问题…...

3 步走,快速上手 API 接口测试

开始 API 接口测试之前,我们需要弄清接口测试的含义: 接口测试就是根据接口清单,模拟客户端向服务端发送请求数据,并获取响应数据后,查看响应数据是否符合预期的过程。 整个过程可以分为三个步骤: 第一步&…...

爬虫-day1-正则表达式作业

利用正则表达式完成下面的操作: 一、不定项选择题 能够完全匹配字符串"(010)-62661617"和字符串"01062661617"的正则表达式包括(ABD ) A. r"\(?\d{3}\)?-?\d{8}" B. r"[0-9()-]" C. r"[0-9(-)]*\d*&…...

【半监督医学图像分割 2023 CVPR】RCPS

文章目录【半监督医学图像分割 2022 CVPR】RCPS摘要1. 介绍2. 相关工作2.1 医学图像分割2.1 半监督学习2.3 对比学习3. 方法3.1 整体概述3.2 纠正伪监督3.3 双向Voxel对比学习。4. 实验【半监督医学图像分割 2022 CVPR】RCPS 论文题目:RCPS: Rectified Contrastive …...

【UVM实战练习项目】2、UVM验证环境基本框架搭建(实例一)(纯软件环境,方便日后测试使用)

本节基于DUT完成UVM验证环境的基本框架搭建,实现对UVM理论知识点进行巩固练习,具体内容包括:如何创建激励、如何建立sequencer、如何连接sequencer和driver,如何集成agent、如何构建env等。 正式开始之前让我们再来回顾下搭建验证环境的过程:首先进行数据建模sequence_ite…...

【web前端初级课程】第四章 什么是JavaScript

目录 一、JavaScript在前端的三种写法 二、常见的弹框 三、变量 四、常量 五、数据类型 六、运算符 七、循环及函数 八、相关练习 前言 JavaScript是一个面向对象的,弱数据类型的,解释型的,动态脚本语言。 面向对象更符合我们对事物…...

数字中国建设进行时:吉林大学党委常务副书记冯正玉一行调研实在智能

两会前夕,中共中央、国务院印发了《数字中国建设整体布局规划》,明确了加快数字中国建设的重点任务。《规划》强调,要加强整体谋划、统筹推进,把各项任务落到实处。在强化人才支撑的第四要点上,指出统筹布局一批数字领…...

面试官灵魂拷问[二]:SQL 语句中 where 条件后写上 1=1 是什么意思?

面试官灵魂拷问系列又来更新啦! “SQL 语句中 where 条件后写上 11 是什么意思?” 这玩意就跟很多新语言支持尾部逗号的原理一样的。 比如 Kotlin 支持数组写成 [1, 2, 3, 4, ] ,注意4后边那个逗号,为什么呢?因为当你增加一个项…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

条件运算符

C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器

一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下&#xff0c;音视频内容犹如璀璨繁星&#xff0c;点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频&#xff0c;到在线课堂中知识渊博的专家授课&#xff0c;再到影视平台上扣人心弦的高清大片&#xff0c;音…...

土建施工员考试:建筑施工技术重点知识有哪些?

《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目&#xff0c;核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容&#xff0c;附学习方向和应试技巧&#xff1a; 一、施工组织与进度管理 核心目标&#xff1a; 规…...