Vue3+nodejs全栈项目(资金管理系统)——后端篇(一)登录、注册

news/2024/4/24 8:48:31/文章来源:https://blog.csdn.net/weixin_45732235/article/details/128008481

文章目录

  • 初始化
    • 创建项目
    • 配置跨域
    • 配置解析表单数据的中间件
    • 安装bodyparser
    • 初始化用户路由模块
    • 抽离用户路由模块中的处理函数
  • 登录注册
    • 新建admin表
    • 安装并配置mysql模块
    • 注册
      • 检测表单数据是否合法
      • 检测用户名是否被占用
      • 对密码进行加密处理bcryptjs
      • 插入新用户
      • 测试
    • 登录
      • 根据名字查询用户的数据
      • 判断用户输入的密码是否正确
      • 生成 JWT 的 Token 字符串
      • 测试

初始化

创建项目

  1. 新建node-app文件夹作为项目根目录,并在根目录中运行以下命令,初始化包管理配置文件
npm init -y

在这里插入图片描述

  1. 运行以下命令,安装特定版本express
npm i express@4.17.1
  1. 在根目录下新建app.js作为项目入口文件,并初始化以下代码:
// 导入express模块
const express = require('express')// 导入expressd的服务器实例
const app = express()// 调用app.listen方法,指定端口号并启动web服务器
app.listen(3000, () => {console.log(`api server running at http://127.0.0.1:3000`)
})

配置跨域

  1. 运行以下命令,安装cors中间件:
npm i cors@2.8.5
  1. app.js 中导入并配置 cors 中间件:
// 导入 cors 中间件
const cors = require('cors')
// 将 cors 注册为全局中间件
app.use(cors())

配置解析表单数据的中间件

通过如下的代码,配置解析 application/x-www-form-urlencoded 格式的表单数据的中间件:

app.use(express.urlencoded({ extended: false }))

安装bodyparser

登录、注册要使用post请求 安装body-parser

npm install body-parser

const bodyParser = require("body-parser")
// 使用body-parse中间件 要放在路由之前
//app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

初始化用户路由模块

  1. router 文件夹中,新建 admin.js 文件,作为管理员的路由模块,并初始化代码如下:
const express = require('express')
// 创建路由对象
const router = express.Router()// 注册
router.post('/register', (req, res) => {res.send('register')
})// 登录
router.post('/login', (req, res) => {res.send('login')
})// 将路由对象共享出去
module.exports = router
  1. app.js 中,导入并使用管理员路由模块:
// 处理管理员(&用户)登录注册相关的路由
const adminRouter = require('./router/admin')
app.use('/api/admin', adminRouter)

抽离用户路由模块中的处理函数

目的:为了保证 路由模块 的纯粹性,所有的 路由处理函数,必须抽离到对应的 路由处理函数模块

  1. /router_handler/admin_handler.js 中,使用 exports 对象,分别向外共享如下两个路由处理函数 :
/*** 在这里定义和登录注册相关的路由处理函数* 供/router/admin.js模块进行调用*/// 注册用户的处理函数
exports.register = (req, res) => {res.send('register')
}// 登录的处理函数
exports.login = (req, res) => {res.send('login')
}
  1. /router/admin.js中的代码修改为如下结构:
const express = require('express')
// 创建路由对象
const router = express.Router()// 导入登录注册处理函数模块
const adminHandler = require('../router_handler/admin_handler')// 注册
router.post('/register', adminHandler.register)// 登录
router.post('/login', adminHandler.login)// 将路由对象共享出去
module.exports = router

登录注册

新建admin表

manage数据库中,新建admin表如下:
在这里插入图片描述

安装并配置mysql模块

在 API 接口项目中,需要安装并配置 mysql 这个第三方模块,来连接和操作 MySQL 数据库

  1. 运行以下命令,安装mysql模块:
npm i mysql@2.18.1
  1. 在根目录下中新建/db/index.js文件,在此自定义模块中创建数据库的连接对象:
// 导入mysql模块
const mysql = require('mysql')// 创建数据库连接对象
const db = mysql.createPool({host: '127.0.0.1',user: 'root',password: 'IKUN1220',database: 'manage'
})// 向外共享db数据库连接对象
module.exports = db

注册

检测表单数据是否合法

  1. 判断namepassword是否为空
const adminInfo = req.body
if (!adminInfo.name || !adminInfo.password) {return res.json({ status: 400, message: '用户名或密码为空' })
}

检测用户名是否被占用

  1. 导入数据库操作模块:
const db = require('../db/index')
  1. 定义sql语句:
const sql = `select * from admin where name = ? `
  1. 执行 SQL 语句并根据结果判断用户名是否被占用:
db.query(sql, [adminInfo.name], (err, results) => {// 执行sql语句失败if (err) {return res.send({status: 404,message: err.message})}// 用户名被占用if (results.length > 0) {return res.status(400).json('用户名已被注册,请更改后重新注册!')}// TODO: 用户名可用,继续之后流程
})

对密码进行加密处理bcryptjs

为了保证密码的安全性,不建议在数据库以 明文 的形式保存用户密码,推荐对密码进行 加密存储

在当前项目中,使用 bcryptjs 对用户密码进行加密,优点:

  • 加密之后的密码,无法被逆向破解
  • 同一明文密码多次加密,得到的加密结果各不相同,保证了安全性
  1. 运行如下命令,安装指定版本的 bcryptjs
npm i bcryptjs@2.4.3
  1. /router_handler/admin.js 中,导入 bcryptjs
const bcrypt = require('bcryptjs')
  1. 在注册用户的处理函数中,确认用户名可用之后,调用bcrypt.hashSync(明文密码, 随机盐的长度)方法,对用户的密码进行加密处理:
// 对用户的密码,进行 bcrype 加密,返回值是加密之后的密码字符串
adminInfo.password = bcrypt.hashSync(adminInfo.password, 10)

插入新用户

  1. 定义插入用户的sql语句
const sqlStr = 'insert into admin set ?'

2.db.query()执行 SQL 语句,插入新用户:

db.query(sqlStr, { name: adminInfo.name, password: adminInfo.password, identify: adminInfo.identify }, (err, results) => {if (err) {return res.send({status: 400,message: err.message})}if (results.affectedRows !== 1) {return res.status(400).json('注册用户失败,请稍后再试')}res.json({status: 200,message: '注册成功',name: adminInfo.name,password: adminInfo.password,identify: adminInfo.identify})
})})

此时router_handler/amdin_handler.js为:

/*** 在这里定义和登录注册相关的路由处理函数* 供/router/admin.js模块进行调用*/
const db = require('../db/index')
const bcrypt = require('bcryptjs')// 注册用户的处理函数
exports.register = (req, res) => {const adminInfo = req.bodyif (!adminInfo.name || !adminInfo.password) {return res.json({ status: 400, message: '用户名或密码为空' })}const sql = `select * from admin where name = ? `db.query(sql, [adminInfo.name], (err, results) => {if (err) {return res.send({status: 404,message: err.message})}if (results.length > 0) {return res.status(400).json('用户名已被注册,请更改后重新注册!')}// 对用户的密码,进行 bcrype 加密,返回值是加密之后的密码字符串adminInfo.password = bcrypt.hashSync(adminInfo.password, 10)const sqlStr = 'insert into admin set ?'db.query(sqlStr, { name: adminInfo.name, password: adminInfo.password, identify: adminInfo.identify }, (err, results) => {if (err) {return res.send({status: 400,message: err.message})}if (results.affectedRows !== 1) {return res.status(400).json('注册用户失败,请稍后再试')}res.json({status: 200,message: '注册成功',name: adminInfo.name,password: adminInfo.password,identify: adminInfo.identify})})})
}// 登录的处理函数
exports.login = (req, res) => {res.send('login')
}

测试

在这里插入图片描述在这里插入图片描述

登录

根据名字查询用户的数据

  1. 接收表单数据:
const adminInfo = req.body
  1. 定义sql语句:
const sql = `select * from admin where name = ?`
  1. 执行sql语句,查询用户的数据:
db.query(sql, adminInfo.name, (err, results) => {if (err) {return res.status(400).json(err)}if (results.length !== 1) {return res.status(400).json('用户不存在')}})

判断用户输入的密码是否正确

核心实现思路:调用 bcrypt.compareSync(用户提交的密码, 数据库中的密码) 方法比较密码是否一致
返回值是布尔值(true 一致、false 不一致)

// 拿着用户输入的密码,和数据库中存储的密码进行对比
const compareResult = bcrypt.compareSync(adminInfo.password, results[0].password)// 如果对比的结果为false,则证明用户输入的密码错误
if(!compareResult) {return res.status(400).json('用户名或密码输入错误,请重新输入')
}

生成 JWT 的 Token 字符串

核心注意点:在生成 Token 字符串的时候,一定要剔除 密码 的值

通过 ES6 的高级语法,快速剔除 密码的值:

// 剔除完毕之后,admin 中只保留了用户的 id,name, identify 这四个属性的值
const admin = { ...results[0], password: '' }
或者
const admin = {id: results[0].id,name: results[0].name,identify: results[0].identify
}

运行如下的命令,安装生成 Token 字符串的包:

npm i jsonwebtoken@8.5.1

/router_handler/admin_handler.js模块的头部区域,导入jsonwebtoken包:

// 用这个包来生成 Token 字符串
const jwt = require('jsonwebtoken')

创建 config.js 文件,并向外共享 加密 和 还原 Token jwtSecretKey 字符串:

module.exports = {jwtSecretKey: 'zhanglijun',
}

将用户信息对象加密成 Token 字符串(/router_handler/admin_handler.js):

// 导入配置文件
const config = require('../config')// 生成 Token 字符串
const tokenStr = jwt.sign(admin, config.jwtSecretKey, {expiresIn: '10h', // token 有效期为 10 个小时
})

将生成的 Token 字符串响应给客户端:

res.json({status: 200,message: '登录成功!',// 为了方便客户端使用 Token,在服务器端直接拼接上 Bearer 的前缀token: 'Bearer ' + tokenStr,
})

测试

在这里插入图片描述在这里插入图片描述在这里插入图片描述
admin_hadler.js代码:

/*** 在这里定义和登录注册相关的路由处理函数* 供/router/admin.js模块进行调用*/
const db = require('../db/index')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const config = require('../config')// 注册用户的处理函数
exports.register = (req, res) => {const adminInfo = req.bodyif (!adminInfo.name || !adminInfo.password) {return res.json({ status: 400, message: '用户名或密码为空' })}const sql = `select * from admin where name = ? `db.query(sql, [adminInfo.name], (err, results) => {if (err) {return res.send({status: 404,message: err.message})}if (results.length > 0) {return res.status(400).json('用户名已被注册,请更改后重新注册!')}// 对用户的密码,进行 bcrype 加密,返回值是加密之后的密码字符串adminInfo.password = bcrypt.hashSync(adminInfo.password, 10)const sqlStr = 'insert into admin set ?'db.query(sqlStr, { name: adminInfo.name, password: adminInfo.password, identify: adminInfo.identify }, (err, results) => {if (err) {return res.send({status: 400,message: err.message})}if (results.affectedRows !== 1) {return res.status(400).json('注册用户失败,请稍后再试')}res.json({status: 200,message: '注册成功',name: adminInfo.name,password: adminInfo.password,identify: adminInfo.identify})})})
}// 登录的处理函数
exports.login = (req, res) => {const adminInfo = req.bodyconst sql = `select * from admin where name = ?`db.query(sql, adminInfo.name, (err, results) => {if (err) {return res.status(400).json(err)}if (results.length !== 1) {return res.status(400).json('用户不存在')}const compareResult = bcrypt.compareSync(adminInfo.password, results[0].password)if (!compareResult) {return res.status(400).json('用户名或密码输入错误,请重新输入')}// const admin = { ...results[0], password: '' }const admin = {id: results[0].id,name: results[0].name,identify: results[0].identify}const tokenStr = jwt.sign(admin, config.jwtSecretKey, {expiresIn: '10h', // token 有效期为 10 个小时})// 将生成的 Token 字符串响应给客户端res.json({status: 200,message: '登录成功!',// 为了方便客户端使用 Token,在服务器端直接拼接上 Bearer 的前缀token: 'Bearer ' + tokenStr,})})
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_224932.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java基础知识+必考面试题(分享收藏版)

在学习Java语言之前,我们要了解相关知识体系,才能更好的掌握学习。那么下面我们就一起来学习JAVA语言吧~ Java语言概述 Java语言是Sun公司在1995年推出的高级编程语言,编程语言就是计算机语言,人们可以通过使用编程语言让计算机完…

红黑树C++实现

目录 一、红黑树的概念 二、红黑树的性质 三、红黑树节点的定义 四、红黑树的插入 4.1 插入节点 4.2 插入节点的颜色 4.3 调整情况1 4.4 调整情况2 4.5 调整情况3 4.6 调整情况总结 五、调整的实现 5.1 调整的步骤分析 5.2 代码实现 六、树的平衡判断 七、源代码…

一文让你了解数据采集

随着云计算、大数据、人工智能的发展,数据采集作为数据的重要手段,成为广大企业的迫切需求。 所谓“得数据者,得人工智能”,如今人工智能早已在我们的生活中屡见不鲜。如“人脸识别”、“语音唤醒音响”等都属于人工智能的范畴。…

擎创技术流 | ClickHouse实用工具—ckman教程(4)

《使用CKman导入集群》 CKman(ClickHouse Manager)是由擎创科技自主研发的一款管理ClickHouse的工具,前端用Vue框架,后端使用Go语言编写。它主要用来管理ClickHouse集群、节点以及数据监控等,致力于服务ClickHouse分布…

总结我的 MySQL 学习历程,给有需要的人看

作者| 慕课网精英讲师 马听 你好,我是马听,现在是某零售公司的 MySQL DBA,身处一线的我表示有很多话要讲。 我的MySQL学习历程 在我大三的时候,就开始接触到 MySQL 了,当时我也是从最基础的 MySQL 知识(…

如何实现办公自动化?

办公自动化(OA)允许数据在没有人工干预的情况下流动。由于人工操作被排除在外,所以没有人为错误的风险。如今,办公自动化已经发展成无数的自动化和电子工具,改变了人们的工作方式。 办公自动化的好处 企业或多或少依…

[附源码]计算机毕业设计JAVA领导干部听课评课管理系统

[附源码]计算机毕业设计JAVA领导干部听课评课管理系统 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM…

【LeetCode与《代码随想录》】哈希表篇:做题笔记与总结-JavaScript版

文章目录代码随想录主要题目242. 有效的字母异位词349. 两个数组的交集202. 快乐数1. 两数之和(经典哈希)454. 四数相加 II15. 三数之和(双指针)18. 四数之和(双指针)相关题目383. 赎金信49. 字母异位词分组…

Python遥感开发之GDAL读写遥感影像

Python遥感开发之GDAL读写遥感影像1 读取tif信息方法一2 读取tif信息方法二3 自己封装读取tif的方法(推荐)4 对读取的tif数据进行简单运算5 写出tif影像(推荐)前言:主要介绍了使用GDAL读写遥感影像数据的操作,包括读取行、列、投影…

从零学习 InfiniBand-network架构(八) —— IB协议中的原子操作

从零学习 InfiniBand-network架构(八) —— IB协议中的原子操作 🔈声明: 😃博主主页:王_嘻嘻的CSDN主页 🔑未经作者允许,禁止转载 🚩本专题部分内容源于《InfiniBand-net…

Docker——容器命令介绍、创建Nginx容器与Redis容器

目录 一、容器命令 二、创建并运行Nginx容器 1.1 去dockerhub查看Nginx容器运行命令 1.2 怎么访问Nginx? 1.3 查看容器日志 1.4总结 三、进入Nginx容器并修改HTML内容 3.1 进入容器 3.2 进入Nginx的HTML所在目录 3.3 修改index.html文件(容器内修…

【OpenEVSE 】汽车充电桩控制项目解析

【OpenEVSE 】汽车充电桩控制项目解析1. 项目介绍2. 项目硬件3. 软件原理以及流程4. 系统结构:ESP32RAPI APIMQTT 上的 RAPI:5. SAE J1772协议简析:6. 专用充电接插件7 . 源码解析:此项目来源于openEnergyMonitor 的 openEVSE 部分&#xff0…

查阅必备----常用的SQL语句,配语句和图解超详细,不怕你忘记

👨‍💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 **收录于专栏 数据库 ⭐查阅必备–常用的SQL语句⭐ 文章目录⭐查阅必备--常用的SQL语句⭐一,关键语句大全&am…

python离线安装module以及常见问题及解决方案

文章目录一,离线安装module1.1 下载module1.2 离线安装二,常见的问题2.1 模块缺少合适的适配:error: Could not find suitable distribution for Requirement.parse()2.2 install成功但发现控制台打印的最后一行显示下载module版本为0.0.0工作…

微信商城小程序怎么开发_分享微信商城小程序的搭建

如何搭建好一个微信商城?这三个功能要会用! 1.定期低价秒杀,提高商城流量 除了通过私域流量裂变,低价秒杀是为商城引流提高打开率的良好手段。 以不同节日作为嘘头,在情人节、38妇女节、中秋国庆、七夕节等日子&…

机器学习-回归模型相关重要知识点

目录01 线性回归的假设是什么?02 什么是残差,它如何用于评估回归模型?03 如何区分线性回归模型和非线性回归模型?04 什么是多重共线性,它如何影响模型性能?05 异常值如何影响线性回归模型的性能&#xff1f…

R语言结课及Matlab开始

R语言结课 我们R语言的学习这节课下课就结束了,接下来进行Matlab的学习。下面我会说一下R的结课任务及如何考试,以及我自己整理的Matlab安装教程。 R的结课作业:周二上课时提到的两个回归模型课程总结(老师说作业总结主要是作业…

通过ref进行组件间的通信

ref&#xff1a;绑定dom节点&#xff0c;拿到的就是dom对象&#xff1b; ref&#xff1a;绑定组件&#xff0c;拿到的就是组件对象&#xff1b; ref绑在dom节点上&#xff1a; //绑在dom上&#xff0c; <input type"text" ref"mytext"> <input…

SpringBoot SpringBoot 开发实用篇 6 监控 6.3 actuator

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇6 监控6.3 actuator6.3.1 actuator6.3.2 监控原理6.3.3 小结6 监控 …

IOS逆向初探

前言 这些文章用于记录学习路上的点点滴滴&#xff0c;也希望能给到刚入门的小伙伴们一点帮助。爱而所向&#xff0c;不负所心。 环境 iphone 6 MacOS Monterey 12.3.1 一、IOS开发语言 Objective-C Objective-C是iOS操作系统运用的软件开发语言。Objective-C的流行完全是因…