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://xiahunao.cn/news/3247737.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

破解反爬虫策略 /_guard/auto.js(二)实战

这次我们用上篇文章讲到的方法来真正破解一下反爬虫策略&#xff0c;这两个案例是两个不同的网站&#xff0c;一个用的是 /_guard/auto.js&#xff0c;另一个用的是/_guard/delay_jump.js。经过解析发现这两个网站用的反爬虫策略基本是一模一样&#xff0c;只不过在js混淆和生成…

高通Android 12 设置Global属性为null问题

1、最近在做app调用framework.jar需求&#xff0c;尝试在frameworks/base/packages/SettingsProvider/res/values/defaults.xml增加属性 <integer name"def_xxxxx">1</integer> 2、在frameworks\base\packages\SettingsProvider\src\com\android\provide…

2024年“数据要素×”大赛宁夏分赛正式启动

数据赋能 乘数而上 分赛聚焦“数据赋能 乘数而上”主题&#xff0c;对标国家“数据要素”大赛要求&#xff0c;结合宁夏特色优势产业、重点行业发展&#xff0c;设立工业制造、现代农业、金融服务、医疗健康、现代教育、水利应用6个行业赛道和1个通用赛道&#xff0c;围绕22个…

linux进程——概念理解与PCB

前言&#xff1a;本篇讲解Linux进程概念相关内容。 操作系统被称为计算机世界的哲学&#xff0c; 可以见得操作系统的知识并不好理解。 对于这篇进程概念的讲解&#xff0c; 博主认为&#xff0c; 如果没有一些前置知识的话&#xff0c;里面的有些概念并不好理解。 但是如果学习…

STM32测测速---编码电机读取速度的计算

1、首先先了解一下计算的公式 速度计算&#xff1a; 轮胎每转一圈的脉冲数取决于编码器的分辨率&#xff0c;可由下面公式进行计算&#xff1a; PPR是电机的线数 以GA25-370电机为例。 图片来源&#xff1a;第四节&#xff1a;STM32定时器&#xff08;4.JGA25-370霍尔编码器…

navicat15已连接忘记密码

1.导出链接 2.使用文本打开 connections.ncx UserName"root" PasswordXXXX 3.复制加密密码&#xff0c;在线解密 代码在线运行 - 在线工具 php解密代码 <?php class NavicatPassword {protected $version 0;protected $aesKey libcckeylibcckey;protected…

vue3 快速入门 (二) : 实现第一个Vue网页,并在手机上浏览

1. 最简单的一个VUE网页 首先&#xff0c;我们可以看我的这篇文章 : vue3 快速入门 (一) : 环境配置与搭建 完成环境搭建。 接着就可以来实现我们的第一个Vue网页了。 本文环境 Vue版本 : 3.4.29Node.js版本 : v20.15.0系统 : Windows11 64位IDE : VsCode 1.1 基础模板 vu…

leetcode热题100-技巧-只出现一次的数字

题源 136.只出现一次的数字 题目描述 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题&#xff0c;且该算法只使用常量额外空间…

未来职场:人工智能就业,人类失业

未来职场&#xff1a;人工智能就业&#xff0c;人类失业 在当今这个快速发展的时代&#xff0c;人工智能和自动化技术的迅猛进步不仅改变了我们的生活方式&#xff0c;也对各行各业产生了深远的影响。从无人驾驶汽车到自动化建筑技术&#xff0c;从机器翻译到智能法律咨询&…

[日进斗金系列]用码上飞解决企微开发维修管理系统的需求

前言&#xff1a; 今天跟大家唠唠如何用小money生 大money的方法&#xff0c;首先我们需要准备一个工具。 这个工具叫码上飞CodeFlying&#xff0c;它是目前国内首发的L4级自动化智能软件开发平台。 它可以在短时间内&#xff0c;与AI进行几轮对话就能开发出一个可以解决实际…

torch学习:均值和方差

torch学习&#xff1a;均值和方差 初始化Relu对方差的影响He Kaiming Normal欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居…

轨道交通AR交互教学定制公司优选深圳华锐视点

在寻找上海AR开发制作公司作为合作伙伴的过程中&#xff0c;选择一家既技术深厚又具备丰富经验的AR开发企业&#xff0c;成为了众多客户与合作伙伴的共同追求。华锐视点上海AR开发制作公司作为业界的佼佼者&#xff0c;凭借其卓越的公司规模、丰富的行业案例以及顶尖的ar增强现…

usb2.0的同步和自动重传机制

1. usb2.0主机和设备的时间同步 usb 主机(host) 通过 SOF(Start-of-Frame) 向 device设备 广播时间&#xff0c;用以时间同步。 1.1 SOF(Start-of-Frame) 格式 1.2 SOF的作用 usb2.0 主机(host) 周期性的向 设备(device) 广播 SOF(Start-of-Frame), SOF(Start-of-Frame) 将总…

N沟道功率高压MOSFET WPH4003-1E 在工业自动化控制中的应用

1700V高压MOSFET WPH4003-1E 具有低导通电阻和高速开关&#xff0c;有助于需要高压电源的工业设备相关应用的低功耗和高效率。WPH4003-1E 反激式电路可以通过减少零件数量来实现“简化栅极驱动电路”和“减少基板面积”的“成本效益”和“环保”应用。 其部分参数如下&#xf…

ubuntu24.04 linux bcm94352hmb 无线网卡(带蓝牙功能)无法连接蓝牙设备的解决办法

ubuntu24.04 linux bcm94352hmb 无线网卡&#xff08;带蓝牙功能&#xff09;无法连接蓝牙设备的解决办法 问题描述 小本是自己换装的bcm94352hmb&#xff0c;现在跑不动黑苹果了&#xff0c;换装ubuntu&#xff0c;该网卡在黑苹果上和windows上都能正常工作&#xff0c;到了…

部署运维之二:虚拟化

摘要&#xff1a; 在21世纪初的曙光中&#xff0c;虚拟化技术悄然萌芽&#xff0c;标志着计算领域的一次革命性飞跃。这一时期&#xff0c;通过引入虚拟化技术&#xff0c;业界实现了在单一物理服务器之上并行运行多个虚拟机的壮举&#xff0c;每个虚拟机均构筑起一个隔离而独…

牛客 7.13 月赛(留 C逆元 Ddp)

B-最少剩几个&#xff1f;_牛客小白月赛98 (nowcoder.com) 思路 奇数偶数 奇数&#xff1b;奇数*偶数 奇数 所以在既有奇数又有偶数时&#xff0c;两者结合可以同时删除 先分别统计奇数&#xff0c;偶数个数 若偶个数大于奇个数&#xff0c;答案是偶个数-奇个数 若奇个数…

网络编程-TCP/IP

网络概述 网络采用分而治之的方法设计&#xff0c;将网络的功能划分为不同的模块&#xff0c;以分层的形式有机组合在一起。 每层实现不同的功能&#xff0c;其内部实现方法对外部其他层次来说是透明的。每层向上层提供服务&#xff0c;同时使用下层提供的服务 网络体系结构…

[RuoYi-Vue] - 6. 若依二次开发

文章目录 &#x1f333;1. 模块定制(修改包名)1.1 若依框架修改器1.2 使用示例 &#x1f33f;2. 新建业务模块2.1 新建子模块2.2 版本锁定2.3 添加模块依赖 &#x1f33e;3. 菜品管理开发3.1 准备SQL并导入数据库3.2 配置代码生成信息3.3 下载代码并导入项目 &#x1f343;4. 通…

【Leetcode】十五、深度优先搜索 宽度优先搜索 :二叉树的层序遍历

文章目录 1、深度优先搜索算法2、宽度优先搜索算法3、leetcode102&#xff1a;二叉树的层序遍历4、leetcode107&#xff1a;二叉树的层序遍历II5、leetcode938&#xff1a;二叉搜索树的范围和 1、深度优先搜索算法 深度优先搜索&#xff0c;即DFS&#xff0c;从root节点开始&a…