【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后边那个逗号,为什么呢?因为当你增加一个项…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

2025-05-08-deepseek本地化部署
title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...
k8s从入门到放弃之Pod的容器探针检测
k8s从入门到放弃之Pod的容器探针检测 在Kubernetes(简称K8s)中,容器探测是指kubelet对容器执行定期诊断的过程,以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...

python可视化:俄乌战争时间线关键节点与深层原因
俄乌战争时间线可视化分析:关键节点与深层原因 俄乌战争是21世纪欧洲最具影响力的地缘政治冲突之一,自2022年2月爆发以来已持续超过3年。 本文将通过Python可视化工具,系统分析这场战争的时间线、关键节点及其背后的深层原因,全面…...