node.js(express.js)+mysql实现登录功能

文章目录

  • 前言
      • 实现步骤
  • 实现步骤
      • 一、检测登录表单的数据是否合法
        • (3)新建schema/user.js
        • (4)在routes/use.js中引入schema/user.js中的方法reg_login_schema,代码如下:
      • 二、根据用户名查询用户的数据
      • 三、判断用户输入的密码是否正确
      • 四、生成JWT 的 Token 字符串
  • 最终登录接口代码如下:
      • 五、在app.js中注册路由之前,配置解析token的中间件,为了指定那些接口不需要进行Token 的身份认证


前言

实现步骤

1.检测表单数据是否合法
2.根据用户名查询用户的数据
3.判断用户输入的密码是否正确
4.生成JWT 的 Token 字符串


登录接口完整代码如下:controllers/user.js文件

// 登录接口
var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");
// 导入jwt 包来生成token
const jwt = require("jsonwebtoken");
// 导入密钥
const config = require("../config");
exports.login = (req, res) => {// 获取客户端提交到服务器的用户信息const userinfo = req.body;// 定义sql语句,根据用户名查询用户的信息const sql = `select * from ev_users where username=?`;// 执行sql语句,根据用户名查询用户的信息db.query(sql, userinfo.username, (err, results) => {// 执行sql语句失败if (err) return res.cc(err);// 执行sql语句成功,但是获取到的数据条件不等于1if (results.length !== 1) return res.cc("登录失败!");// 判断密码是否和数据库中的密码是否一致// compareSync 第一个参数用户输入的,第二个参数数据库查询到的// 返回值为ture 一致,反之const compareResult = bcrypt.compareSync(userinfo.password,results[0].password);console.log("1", userinfo.password);console.log("2", results[0].password);if (!compareResult) {return res.cc("登录失败233");}// 生成jwt的token字符串// 清空用户信息的密码和头像const user = { ...results[0], password: "", user_pic: "" };console.log(user);// 对用户的信息进行加密,生成token字符串const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: "10h", // token 有效期为10小时});// 将生成的token字符串响应给客户端res.send({status: 0,message: "登录成功!",// 为了方便客户端使用,在服务器端直接拼接上Bearer的前缀// 注意:Bearer 后面必须有空格token: "Bearer "+ tokenStr,});// res.cc("ok");});
};

实现步骤

一、检测登录表单的数据是否合法

1)安装 jOi 包,为表单中携带的每个数据项,定义验证规则:

npm install joi

(2)安装 @escook/express-j01 中间件,来实现自动对表单数据进行验证的功能:

npm install @escook/express-joi
(3)新建schema/user.js
// 导入定义验证规则的包
// const joi = require("@hapi/joi");
const joi = require("joi");
/*** string()值必须是字符串* alphanum()值只能包含a-zA-ZO-9的字符串* min(length) 最小长度* max(length) 大长度* required() 值是必填项,不能为 undefined* pattern(正则表达式) 值必须符合正则表达式的规则*/// 定义用户名和密码的验证规则
const username = joi.string().alphanum().min(1).max(10).required();
const password = joi.string().pattern(/^[\S]{6,12}$/).required();
// 定义验证注册和登录表单数据的规则对象
exports.reg_login_schema = {body: {username,password,},
};
(4)在routes/use.js中引入schema/user.js中的方法reg_login_schema,代码如下:
var express = require("express");
var router = express.Router();
// 引入封装的获取验证码的方法
var unr_handler = require("../controllers/user");// 1.导入验证数据的中间件
const expressJoi = require("@escook/express-joi");
//  2.导入需要的验证规则对象
const { reg_login_schema } = require("../schema/user");// 新用户注册
// router.post("/regUser", expressJoi(reg_login_schema), unr_handler.regUser);
// router.post("/regUser", unr_handler.regUser);
// 登录
router.post("/login", expressJoi(reg_login_schema), unr_handler.login);
module.exports = router;

二、根据用户名查询用户的数据

var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");
// 导入jwt 包来生成token
const jwt = require("jsonwebtoken");
// 导入密钥
const config = require("../config");
// 登录接口
exports.login = (req, res) => {// 获取客户端提交到服务器的用户信息const userinfo = req.body;// 定义sql语句,根据用户名查询用户的信息const sql = `select * from ev_users where username=?`;// 执行sql语句,根据用户名查询用户的信息db.query(sql, userinfo.username, (err, results) => {// 执行sql语句失败if (err) return res.cc(err);// 执行sql语句成功,但是获取到的数据条件不等于1if (results.length !== 1) return res.cc("登录失败!");// res.cc("ok");});
};

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

// 导入密码加密
const bcrypt = require("bcryptjs");
exports.login = (req, res) => {// 获取客户端提交到服务器的用户信息const userinfo = req.body;// 定义sql语句,根据用户名查询用户的信息const sql = `select * from ev_users where username=?`;// 执行sql语句,根据用户名查询用户的信息db.query(sql, userinfo.username, (err, results) => {// 执行sql语句失败if (err) return res.cc(err);// 执行sql语句成功,但是获取到的数据条件不等于1if (results.length !== 1) return res.cc("登录失败!");// 判断密码是否和数据库中的密码是否一致// compareSync 第一个参数用户输入的,第二个参数数据库查询到的// 返回值为ture 一致,反之const compareResult = bcrypt.compareSync(userinfo.password,results[0].password);console.log("1", userinfo.password);console.log("2", results[0].password);if (!compareResult) {return res.cc("登录失败233");}// res.cc("ok");});
};

四、生成JWT 的 Token 字符串

1)在生成 Token 字符串的时候,一定要别除 密码 和 头像 的值

  // 清空用户信息的密码和头像const user = { ...results[0], password: "", user_pic: "" };

2)安装成成token的字符串包

npm 1 jsonwebtoken@8.5.1

3)在 /controllers/user.js 模块的头部区域,导入 jsonwebtoken 包:

// 导入jwt 包来生成token
const jwt = require("jsonwebtoken");

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

// 全局的配置文件
module.exports = {// 加密和解密 token 的密钥jwtSecretKey: "itheima No1. ^_^",
};

5)将用户信息对象加密成 Token 字符串, 在controllers/user.js文件引入config.js

// 导入密钥
const config = require("../config");
const user = { ...results[0], password: "", user_pic: "" };console.log(user);// 对用户的信息进行加密,生成token字符串const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: "10h", // token 有效期为10小时});// 将生成的token字符串响应给客户端res.send({status: 0,message: "登录成功!",// 为了方便客户端使用,在服务器端直接拼接上Bearer的前缀token: "Bearer"+ tokenStr,});

最终登录接口代码如下:

// 登录接口
var db = require("../utils/db"); 
// 导入密码加密
const bcrypt = require("bcryptjs");
// 导入jwt 包来生成token
const jwt = require("jsonwebtoken");
// 导入密钥
const config = require("../config");
exports.login = (req, res) => {// 获取客户端提交到服务器的用户信息const userinfo = req.body;// 定义sql语句,根据用户名查询用户的信息const sql = `select * from ev_users where username=?`;// 执行sql语句,根据用户名查询用户的信息db.query(sql, userinfo.username, (err, results) => {// 执行sql语句失败if (err) return res.cc(err);// 执行sql语句成功,但是获取到的数据条件不等于1if (results.length !== 1) return res.cc("登录失败!");// 判断密码是否和数据库中的密码是否一致// compareSync 第一个参数用户输入的,第二个参数数据库查询到的// 返回值为ture 一致,反之const compareResult = bcrypt.compareSync(userinfo.password,results[0].password);console.log("1", userinfo.password);console.log("2", results[0].password);if (!compareResult) {return res.cc("登录失败233");}// 生成jwt的token字符串// 清空用户信息的密码和头像const user = { ...results[0], password: "", user_pic: "" };console.log(user);// 对用户的信息进行加密,生成token字符串const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: "10h", // token 有效期为10小时});// 将生成的token字符串响应给客户端res.send({status: 0,message: "登录成功!",// 为了方便客户端使用,在服务器端直接拼接上Bearer的前缀// 注意:Bearer 后面必须有空格token: "Bearer "+ tokenStr,});// res.cc("ok");});
};

/utils/db文件代码

const mysql = require("mysql");
const db = mysql.createPool({host: "localhost", // 连接地址port: "3306", //端口号user: "root", //用户名password: "XXXXXXX", //密码database: "exapp2", //数据库名
});
module.exports = db;

在这里插入图片描述

五、在app.js中注册路由之前,配置解析token的中间件,为了指定那些接口不需要进行Token 的身份认证

1.安装解析 Token 的中间件:

npm i express-jwt@5.3.3

2). app.js

// 导入配置文件
const config = require("./config");
// 解析token的中间件
const expressJWT = require("express-jwt");
// 使用 unless({ path:[/^\/user\//] )) 指定哪些接口不需要进行 Token 的身份认证
// ps: path: [/^\/user/] 改成你自己的接口前缀path: [/^\/XXX/] 
app.use(expressJWT({ secret: config.jwtSecretKey }).unless({ path: [/^\/user/] })
);

3)在 app.js 中的 错误级别中间件 里面,捕获并处理 Token 认证失败后的错误:

// 定义表单验证失败的错误的中间件,并把验证失败的结果响应给客户端
// 错误中间件
app.use(function (err, req, res, next) {// 数据验证失败,instanceof判断if (err instanceof joi.ValidationError) {return res.cc(err);}// token身份认证失败后的错误if (err.name === "UnauthorizedError") return res.cc("身份认证失败");// 未知错误res.cc(err);
});

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

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

相关文章

触摸按键控制LED灯

目录 1.理论 2.代码 2.1 touch_ctrl_led.v 2.2 tb_touch_ctrl_led 1.理论 以上的波形图的touch_flag是采用组合逻辑的方式产生的。 以上的touch_flag是采用时序逻辑产生的,时序逻辑会延迟一拍。 以上是上升沿和下降沿的组合逻辑和时序逻辑实现,逻辑或…

柏曼、好视力、书客护眼台灯值得入手吗?热门台灯多方位测评对比

近年来学生近视的现象越来越严重了,而且近视的年龄也越来越小了,不少还没开始上小学的孩子,就已经戴上了厚厚的近视眼镜。而那些高年级的学生更是近视的重灾区,每天不仅需要高强度的学习和长时间用眼,甚至晚上都还需要…

27k+ star!有了它 再也不怕忘记linux命令了

简介 linux-command 是一个收集Linux命令的仓库,当前仓库搜集了 580 多个 Linux 命令,是一个非盈利性的仓库,生成了一个 web 网站方便使用,目前网站没有任何广告,内容包含 Linux 命令手册、详解、学习,内容…

护眼灯真能护眼吗知乎?真正能护眼的护眼台灯推荐

最近去了一些有小孩的家庭进行拜访,发现许多父母通常直接使用家中的灯光或者购买几十块钱的超市台灯供孩子写作业使用。然而,他们最后还得花费大量金钱为孩子配眼镜,这种做法实际上得不偿失,因为他们并未意识到家庭灯光对视力的影…

【Docker】Nacos的单机部署及集群部署

一、Nacos的介绍 Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 动态服务发现:Nacos支持DNS与RPC服务发现,提供原生SDK、OpenAPI等多种服务注册方式和DNS、HTTP与API等多种服务发现方式。服务健康监测:Nacos提供…

[渗透测试学习] Hospital - HackTheBox

文章目录 信息搜集getshell提权信息搜集 nmap扫描一下端口 发现8080端口和443端口有http服务 然后发现3389端口是启用了ms-wbt-server服务 在对443端口的扫描没有收获,并且只有邮箱登录界面无法注册 接着看向8080端口,我们随便注册用户登录后发现有文件上传功能 getshell …

RDMA Scatter Gather List详解

1. 前言 在使用RDMA操作之前,我们需要了解一些RDMA API中的一些需要的值。其中在ibv_send_wr我们需要一个sg_list的数组,sg_list是用来存放ibv_sge元素,那么什么是SGL以及什么是sge呢?对于一个使用RDMA进行开发的程序员来说&#…

Solana Mobile开启第二代Saga手机预售,怎么购买Solana Mobile?

PANews 1月17日消息,Solana Mobile官方宣布开启其第二代Saga手机(Chapter 2)的预售,预购押金为450美元,预计将于2025年上半年发货。同时,Chapter 2的发售将会包括推荐(Referrals)和积…

问题:Feem无法发送信息OR无法连接(手机端无法发给电脑端)

目录 前言 问题分析 资源、链接 其他问题 前言 需要在小米手机、华为平板、Dell电脑之间传输文件,试过安装破解的华为电脑管家、小米的MIUI文件传输等,均无果。(小米“远程管理”ftp传输倒是可以,但速度太慢了,且…

“GPC爬虫池有用吗?

作为光算科技的独有技术,在深入研究谷歌爬虫推出的一种吸引谷歌爬虫的手段 要知道GPC爬虫池是否有用,就要知道谷歌爬虫这一概念,谷歌作为一个搜索引擎,里面有成百上千亿个网站,对于里面的网站内容,自然不可…

STM32F103标准外设库——认识STM32(一)

个人名片: 🦁作者简介:一名喜欢分享和记录学习的在校大学生 🐯个人主页:妄北y 🐧个人QQ:2061314755 🐻个人邮箱:2061314755qq.com 🦉个人WeChat:V…

Labview局部变量、全局变量、引用、属性节点、调用节点用法理解及精讲

写本章前想起题主初学Labview时面对一个位移台程序,傻傻搞不清局部变量和属性节点值有什么区别,概念很模糊。所以更新这篇文章让大家更具象和深刻的去理解这几个概念,看完记得点赞加关注喔~ 本文程序源代码附在后面,大家可以自行下…