node+MySQL+Express实现账户登录,注册,重置之登录篇

node+MySQL+Express实现账户登录

        • 实现技术
        • 开发工具
        • 项目结构
        • 效果图
        • app.js代码
        • db.js
        • router下的account.js
        • db下的account.js
        • login.html
        • 数据库结构

实现技术

node.js,MySQL5.7(8.0以上版本会报错)layui(前端框架)Express
notify(消息通知layui插件)

开发工具

编码:vscode
数据库:navicat

项目结构

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

效果图

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

app.js代码

在这里插入图片描述

// 引入express模块
const express = require('express');
const path = require('path');
const { app, pool } =require('./db')
const user = require('./router/account')
// 设置端口号
const port = process.env.PORT || 8080; // 设置默认端口号
// const port = 8080;//设置端口号// 静态资源目录路径
const staticPath = path.join(__dirname, 'public');
// 登录相关页面基础路径
const loginBasePath = path.join(__dirname, 'views/login');// 使用静态资源
app.use(express.static(staticPath));// 页面路由处理
const sendPage = (route, filename) => app.get(route, (req, res) => res.sendFile(path.join(loginBasePath, filename)));// 跳转到登录页面
sendPage('/', 'login.html');
// 跳转到注册页面
sendPage('/register', 'register.html');
// 跳转到重置密码页面
sendPage('/rest', 'restPassword.html');
//  跳转到首页
sendPage('/main', 'main.html');
//跳转到短信验证登录页面
sendPage('/sms', 'smsLogin.html');
// 用户相关路由
app.use('/user', user)// 监听端口
app.listen(port, () => console.log(`服务器在端口 ${port} 上启动成功`));
db.js

在这里插入图片描述

const mysql = require('mysql2')
const express = require('express')
const app = express()
const router = express.Router();// 解析参数
const bodyParser = require('body-parser')
// json请求
app.use(bodyParser.json())
// 表单请求
app.use(bodyParser.urlencoded({extended: false}))
/*** 配置mysql*/
const option = {host: 'localhost',user: 'root',password: 'root',port: '3307',database: 'bookInfo',connectTimeout: 5000, //连接超时multipleStatements: false //是否允许一个query中包含多条sql语句
}
let pool;
repool()
function Res ({ code = 200, msg = '', data = {} }) {this.code = code;this.msg = msg;this.data = data;
}
function resJson (_res, result) {return _res.json(new Res(result))
}
// 断线重连机制
function repool() {// 创建连接池pool = mysql.createPool({...option,waitForConnections: true, //当无连接池可用时,等待(true)还是抛错(false)connectionLimit: 100, //连接数限制queueLimit: 0 //最大连接等待数(0为不限制)})pool.on('error', err => {err.code === 'PROTOCOL_CONNECTION_LOST' && setTimeout(repool, 2000)})app.all('*', (_,__, next) => {pool.getConnection( err => {err && setTimeout(repool, 2000) || next()})})
}
module.exports = { app, pool, router, resJson }
router下的account.js

在这里插入图片描述

const { pool, router, resJson } = require('../db');
const userSQL = require('../db/account');
const path = require('path');/*** 用户登录功能*/
router.post('/login', (req, res) => {// 获取请求参数let user = {account: req.body.account,password: req.body.password};let _res = res;// 判断参数是否为空if (!user.account) {return resJson(_res, {code: -1,msg: '账户不能为空'});}// 判断参数是否为空if (!user.password) {return resJson(_res, {code: -1,msg: '密码不能为空'});}// 从连接池获取连接pool.getConnection((err, conn) => {conn.query(userSQL.queryByNamePassword, [user.account, user.password], (e, result) => {if (e) {return resJson(_res, { code: -1, msg: e });}// 通过用户名和密码索引查询数据有数据说明用户存在且密码正确if (result && result.length) {// 登录成功resJson(_res, {code: 0,msg: '登录成功!'});} else {// 账户或密码错误resJson(_res, {code: -1,msg: '账户或密码错误'});}});pool.releaseConnection(conn); // 释放连接池,等待别的连接使用});
});module.exports = router;
db下的account.js

在这里插入图片描述

const accountSQL = {queryByNamePassword: 'select * from  tb_account where account=? and password=?',  // 通过账户和密码索引查询用户
}module.exports = accountSQL
login.html
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>暖意书籍管理系统登录</title><!-- 设置系统图标 --><link rel="shortcut icon" href="../icon/login.ico" type="image/x-icon" /><!-- 引用layui文件中layui.css --><link rel="stylesheet" href="../layui/css/layui.css"  media="all"></link>
</head>
<style>.login-container{width: 320px; margin: 241px auto 0;}body {background-image: url(../image/login_index.jpg);background-size: cover;background-repeat: repeat;}.register-link-container {text-align: right; /* 右对齐文本 */}</style>
<body>
<form class="layui-form"><div class="login-container"><div class="layui-form-item"><div class="layui-input-wrap"><div class="layui-input-prefix"><i class="layui-icon layui-icon-username"></i></div><input type="number" name="account"  lay-verify="required|phone" placeholder="账户" lay-reqtext="请先填写账户" lay-vertype="tips" autocomplete="off" class="layui-input" lay-affix="clear"></div></div><div class="layui-form-item"><div class="layui-input-wrap"><div class="layui-input-prefix"><i class="layui-icon layui-icon-password"></i></div><input type="password" name="password"  lay-verify="required" placeholder="密   码" lay-reqtext="请填写密码" lay-vertype="tips" autocomplete="off" class="layui-input" lay-affix="eye"></div></div><div class="layui-form-item"><input type="checkbox" name="remember" lay-skin="primary" title="记住密码"><a href="/rest" style="float: right; margin-top: 7px;color: #435594;">忘记密码?</a></div><div class="layui-form-item"><button class="layui-btn layui-btn-fluid layui-bg-black" lay-submit lay-filter="loginBtn">&nbsp;&nbsp;&nbsp;&nbsp;</button></div><div class="layui-form-item"><a href="/sms" style="position: fixed;color: #435594;">短信快捷登录</a><div class="register-link-container"><a href="/register" style="color: #435594;">注册帐号</a></div></div></div>
</form><!-- 请勿在项目正式环境中引用该 layui.js 地址 -->
<script src="../layui/layui.js"></script> 
<script src="../notify/notify.js"></script>
<script>layui.use(['notify'],function(){var $ = layui.$;var form = layui.form;var layer = layui.layer;var util = layui.util;var notify = layui.notify;/* 方法1:利用layui的form模块的进行表单提交事件form.on('submit(loginBtn)', function(data){var field = data.field; // 获取表单字段值var loadIndex = layer.msg('验证登录中,请稍后...', {icon: 16,shade: 0.01});;setTimeout(function(){layer.close(loadIndex);$.ajax({url: 'http://localhost:3000/user/login',type: 'post',data: {account:field.account,password:field.password}, // 数据转换为JSON字符串success: function(res) {if(res.code == 0){layer.msg(res.msg);setTimeout(function(){location.href = 'http://localhost:3000/main';}, 1000);}else{layer.msg(res.msg);}}})}, 2000);// 阻止表单跳转return false; });*/// 方法2: 引用第三方消息通知组件进行表单提交事件form.on('submit(loginBtn)', function(data){var field = data.field; // 获取表单字段值if(field.password.length < 6){notify.info({msg:'密码长度不能小于6位',position:'vcenter',shadow:true, closable:false,duration:1000});return false;}/*加载提示:用法 notify.info({msg:"提示",//提示信息closable:true,//是否显示关闭按钮 默认是trueposition:'vcenter',// 指定弹出位置:默认topCenter,可选值:bottomRight|bottomLeft|topRight|topLeft|topCenter|bottomCenter|vcenter"shadow:true,//  是否显示阴影默认是falseduration:2000,//显示时间默认3000,为 0 时不自动关闭});*/notify.loading({msg:'验证登录中,请稍后...',position:'vcenter',shadow:true, closable:false});//显示加载中setTimeout(function(){notify.destroyAll();//关闭所有通知$.ajax({url: 'http://localhost:8080/user/login',type: 'post',data: {account:field.account,password:field.password}, // 数据转换为JSON字符串success: function(res) {if(res.code == 0){//弹出成功提示notify.success({msg:res.msg,position:'vcenter',shadow:true, closable:false,duration:1000});//跳转到系统首页,延迟500毫秒setTimeout(function(){location.href = 'http://localhost:8080/main';}, 500);}else{//弹出错误提示notify.error({msg:res.msg,position:'vcenter',shadow:true, closable:false,duration:1000});}}})}, 2000);// 阻止表单跳转return false; //如果不加的话,表单不会跳转但不会进行登录操作});});</script></body>
</html>
数据库结构

在这里插入图片描述

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

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

相关文章

如何使用在线工具将手机相册中的图片转换为JPG格式

我们经常在手机相册中保存大量的图片&#xff0c;无论是家庭聚会的照片还是旅行的瞬间&#xff0c;每一幅图像都承载着珍贵的记忆。然而&#xff0c;有时候我们会遇到图片格式不兼容的问题&#xff0c;尤其是在需要将图片分享到特定平台或编辑时。 例如&#xff0c;某些社交平台…

Java语音转文字及文字转语音教学 (离线版)

1. 语音转文字 1.1 maven导入以下包 <!-- 获取音频信息 --> <dependency><groupId>org</groupId><artifactId>jaudiotagger</artifactId><version>2.0.3</version> </dependency><!-- 语音识别 --> <dependen…

C++知识要点总结笔记

文章目录 前言一、c基础1.指针和引用指针和引用的区别函数指针 2.数据类型整型 short int long 和 long long无符号类型强制类型转换 3.关键字conststaticconst和static的区别define 和 typedef 的区别define 和 inline 的区别const和define的区别constexprvolatileextern前置与…

Linux服务器LVM分区扩展

1、检查服务器当前分配磁盘 查看服务器物理磁盘分配情况&#xff0c;可见服务器当前配置磁盘SDA共250G&#xff0c;已划分区sda1:4G&#xff0c;sda2:146G&#xff1b;其中sda2分区分为两个lvm分区&#xff08;centos-root和centos-swap&#xff09;; 查看磁盘分区挂载情况&am…

【实战】安装Webtours

首先&#xff0c;安装jdk。过程如下图。 添加环境变量&#xff0c;如下图。 安装activeperl&#xff0c;如下图。 复制Webtours文件夹到计算机中&#xff0c;之后双击webtours文件夹中的xigui32.exe&#xff0c;启动webtours的应用服务器。 之后&#xff0c;可以在任务栏右下角…

CSA笔记2-文件管理命令

tree 以树状图显示多级目录 示例&#xff1a; [rootlocalhost ~]# tree haha/ haha/ └── 111 └── 222 2 directories, 0 files [rootlocalhost ~]# tree -L 1 haha/haha/ └── 111 echo > >> < << 示例&#xff1a; [rootxxx ~]#…

Linux限速工具:FlowMaster - IP级网络流量控制脚本

目录 前言&#xff1a; Github加速器&#xff1a; 简介 功能 安装方法 使用方法 数值单位 基本命令 选项 示例 启动 FlowMaster 重启 FlowMaster 停止 FlowMaster 查看状态 查看 Iptables 设置 许可证 贡献 联系我们 前言&#xff1a; 在市面上看了好多关于网…

MySQL执行状态查看与分析

当mysql出现性能问题时&#xff0c;一般会查看mysql的执行状态&#xff0c;执行命令&#xff1a; show processlist 各列的含义 列名含义id一个标识&#xff0c;你要kill一个语句的时候使用&#xff0c;例如 mysql> kill 207user显示当前用户&#xff0c;如果不是root&…

比Snipaste还好用的截图工具?

千鹿设计助手&#xff1a;千鹿设计助手官网 - 设计师效率神器 最近新出的一款截图工具千鹿设计助手&#xff0c;比Snipaste功能多一些。在Snipaste功能基础上&#xff0c;还支持长截图&#xff0c;截动图&#xff0c;还实时保留截图记录、支持OCR识别、文本识别、图片智能处理…

【CSS in Depth 2 精译_018】3.1.2 逻辑属性 + 3.1.3 用好逻辑属性的简写形式

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…

Prometheus 云原生 - Prometheus 数据模型、Metrics 指标类型、Exporter 相关

目录 开始 Prometheus 数据类型 简单理解 时序样本 格式 和 命名要求 Metrics 指标类型 Counter 计数器 Gauge Histogram Summary Exporter 相关 概述 Exporter 类型 Exporter 规范 开始 Prometheus 数据类型 简单理解 a&#xff09;安装好 Prometheus 后会暴露…

乘积量化pq:将高维向量压缩 97%

向量相似性搜索在处理大规模数据集时&#xff0c;往往面临着内存消耗的挑战。例如&#xff0c;即使是一个包含100万个密集向量的小数据集&#xff0c;其索引也可能需要数GB的内存。随着数据集规模的增长&#xff0c;尤其是高维数据&#xff0c;内存使用量会迅速增加&#xff0c…

2024年大数据高频面试题(中篇)

文章目录 Kafka为什么要用消息队列为什么选择了kafkakafka的组件与作用(架构)kafka为什么要分区Kafka生产者分区策略kafka的数据可靠性怎么保证ack应答机制(可问:造成数据重复和丢失的相关问题)副本数据同步策略ISRkafka的副本机制kafka的消费分区分配策略Range分区分配策略…

SAP ABAP性能优化分析工具

SAP系统提供了许多性能调优的工具&#xff0c;重点介绍下最常用几种SM50, ST05, SAT等工具&#xff1a; 1.工具概况 1.1 SM50 / SM66 - 工作进程监视器 通过这两个T-code, 可以查看当前SAP AS实例上面的工作进程&#xff0c;当某一工作进程长时间处于running的状态时&#…

每日OJ_牛客_删除公共字符(暴力+哈希)

目录 牛客_删除公共字符 法一代码&#xff08;暴力&#xff09; 法二代码&#xff08;哈希&#xff09; 牛客_删除公共字符 删除公共字符__牛客网 法一代码&#xff08;暴力&#xff09; 暴力查找方式&#xff0c;如判断第一个串的字符是否在第二个串中&#xff0c;在再挪动…

排序——归并排序及排序章节总结

前面的文章中 我们详细介绍了排序的概念&#xff0c;插入排序&#xff0c;交换排序与选择排序&#xff0c;大家可以通过下面的链接再去学习&#xff1a; ​​​​​​排序的概念及插入排序 交换排序 选择排序 这篇文章就详细介绍一下另一种排序算法&#xff1a;归并排序以及…

Uniapp基础篇(持续更新)

1. Uni-app常用内置组件 view 视图容器 scroll-view 可滚动视图区域&#xff0c;用于区域滚动。需注意在webview渲染的页面中&#xff0c;区域滚动的性能不及页面滚动。 swiper 滑块视图容器。一般用于左右滑动或上下滑动&#xff0c;比如banner轮播图。 image uniapp官方iam…

ROS服务通信机制实操Python

ROS服务通信机制实操Python 步骤流程vscode配置服务端客户端编辑配置文件编译并执行优化实现参数的动态提交优化先启动客户端后启动服务端 ROS服务通信的理论查阅&#xff1a;ROS服务通信流程理论 ROS服务通信的自定义srv数据的准备可以查阅&#xff1a;ROS服务通信自定义srv …

【学术会议征稿】第八届控制工程与先进算法国际论坛(IWCEAA 2024)

第八届控制工程与先进算法国际论坛 8th International Workshop on Control Engineering and Advanced Algorithms(IWCEAA 2024) 第八届控制工程与先进算法国际论坛&#xff08;IWCEAA 2024&#xff09;将于2024年11月1-3日在中国南京隆重举行。会议旨在为从事算法、控制工程与…

昇思25天学习打卡营第七天|应用实践/生成式/Diffusion扩散模型

心得 这个课程是一个劝退的课程。讲述了Diffusion扩散模型实现原理。提供了这个原理的一些公式推导。当然看这个推导是需要一定的数学基础的。这个课程这么写&#xff0c;是为了让那些数学不怎么好的&#xff0c;知难而退吗&#xff1f; 这个课程还是一个比较难以复制粘贴的课…