当前位置: 首页 > news >正文

express+mySql实现用户注册、登录和身份认证

express+mySql实现用户注册、登录和身份认证

注册

注册时需要对用户密码进行加密入库,提高账户的安全性。用户登录时再将密码以相同的方式进行加密,再与数据库中存储的密码进行比对,相同则表示登录成功。

安装加密依赖包bcryptjs

cnpm install -S bcryptjs

在注册接口中添加加密功能

// 引入对密码进行加密的包
const bcryptjs = require("bcryptjs");
class User {register(req, res) {let { username, nick_name,  password } = req.body;// 先查找注册的用户名是否在数据库中已存在const sql = "select * from sys_user where user_name=?";pool.query(sql, username, (err, results) => {if (err) return res.sendError(err);// 找到了要注册的用户名if (results.length >= 1) return res.sendError("当前用户名已被占用!");// 对密码进行加密,第二个参数可以提高密码的安全性为任意数字const password1 = bcryptjs.hashSync(password, 10);const SQl = `Insert into sys_user (user_name,password,nick_name) values('${username}', '${password1}', '${nick_name}')`pool.query(SQl, (err, data) => {if (err) return res.sendError(err);if (data.affectedRows !== 1) {res.sendError('用户注册失败"');} else {res.sendSuccess(data);}})})}
}

效果展示

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

登录

安装加密依赖包jsonwebtoken

jsonwebtokenuaokeyi生成用户登录需要的token信息。

cnpm install -S jsonwebtoken

增加全局token配置文件

在项目根目录的config文件夹下新增taken.js文件,并加入如下配置。

// 全局的配置文件
module.exports = {// 设置token加密和解密用到的密钥jwtSecretKey: 'qwertyuiop',// 设置token的有效期expiresIn: '10h',
}

在这里插入图片描述

在登录接口中返回taken信息

// 导入jsonwebtoken
const jwt = require("jsonwebtoken");
// 导入全局配置文件
const taken = require("../config/taken");
class User {login(req, res) {const { username, password } = req.body;// 先查找用户名是否在数据库中,定义sql语句const sql = "select * from sys_user where user_name=?";pool.query(sql, username, (err, results) => {if (err) return res.sendError(err);if (results.length !== 1) return res.sendError("当前用户不存在!");// 比较密码  compareSync(客户端的密码,数据库中存储的经过加密后的密码)会返回true或falseconst compareResult = bcryptjs.compareSync(password, results[0].password);if (!compareResult) {return res.sendError("用户密码错误,登录失败!");}// 密码比对正确,在服务端根据用户信息(用户密码需置空)生成token信息const user = { ...results[0], password: "" };// 对用户的信息进行加密,生成token字符串const tokenStr = jwt.sign(user, taken.jwtSecretKey, {expiresIn: taken.expiresIn,});// 调用res.send将token响应给客户端res.sendSuccess("Bearer " + tokenStr)})}
}

效果展示

在这里插入图片描述

配置系统白名单

白名单是指那些接口不需要提供token信息。

安装解析token的依赖包express-jwt

express-jwt 包需要使用和生成token时相同的密钥。

cnpm install -S express-jwt

修改app.js文件设置系统白名单

// 在路由之前配置解析token的中间件
const { expressjwt: jwt } = require("express-jwt")
// 解析token时需要token的密钥
const taken = require("./config/taken");
// 定义中间件,
// .unless指定哪些接口不需要进行token身份认证(过滤掉swagger页面和login接口)
app.use(jwt({ secret: taken.jwtSecretKey, algorithms: ["HS256"] }).unless({path: [/^\/api-docs/, '/user/login', '/user/register'],})
)

效果展示

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

在其他接口中通过token获取具体的用户信息

在接口中通过req.auth中获取:具体代码如下:

class mineSeam {getAll(req, res) {console.log(req.auth)}
}

在这里插入图片描述

app.js全部代码如下

// 引入express
const express = require("express");
const path = require('path');
const router = require('./routes/index.js');// 创建服务器的实例对象
const app = express();// 配置解析表单数据的中间件,内置中间件只能解析application/x-www-form-urlencoded格式的数据
app.use(express.urlencoded({ extended: false }));// 搭建静态文件服务
app.use(express.static(path.join(__dirname, 'public')));// 引入swagger配置项
const swaggerSpec = require('./config/swagger')
app.get('/swagger.json', function(req, res) {res.setHeader('Content-Type', 'application/json');res.send(swaggerSpec);
});/*** 在路由之前封装res.send()*/
app.use((req, res, next) => {// 定义一个输出的函数res.sendError = function (err) {res.send({code: 400,msg: err instanceof Error ? err.message : err})}// 定义一个输出的函数res.sendSuccess = function (data = null) {res.send({code: 200,msg: '成功',data})}next();
})// 在路由之前配置解析token的中间件
const { expressjwt: jwt } = require("express-jwt");
// 解析token需要token的密钥
const taken = require("./config/taken");
// 定义中间件,需要哪个密钥解析
// algorithms:设置jwt的算法
// .unless指定哪些接口不需要进行token身份认证
app.use(jwt({ secret: taken.jwtSecretKey, algorithms: ["HS256"] }).unless({path: [/^\/api-docs/, '/user/login', '/user/register'],})
)// 引入路由
router(app);// 引入校验规则的包,在定义错误级别的中间件时会用到
const joi = require('joi')
// 在所有路由下面调用错误级别的中间件
app.use((err, req, res, next) => {// 验证失败导致的错误if (err instanceof joi.ValidationError) return res.sendError(err);// 未知的错误res.sendError(err);next();
})// 启动服务器,3007为端口号,选择一个空闲的端口号
app.listen(3007, () => {console.log("Server running at http://127.0.0.1:3007");
})

参考链接

链接1

相关文章:

  • WEB渗透—反序列化(九)
  • golang 集成logrus日志框架
  • 基于SpringBoot的旅游网站的设计与实现
  • Could not resolve all files for configuration ‘:app:androidJdkImage‘.
  • Go语言使用AES加密解密
  • 漏洞复现--致远 M3 反序列化 mobile_portal RCE
  • 原生GPT本地及云端部署方式保姆级教程
  • 嵌入式硬件基础知识——1
  • 【LabVIEW学习】3.labview制作安装程序
  • Kafka 如何实现顺序消息
  • 力扣100. 相同的树
  • redis运维(十五) 集合
  • RPA机器人如何确保敏感数据的安全性
  • 深入解析 Python 中 Parsel 的两种数据提取方式
  • NSSCTF第14页(2)
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • CSS3 变换
  • HTTP中的ETag在移动客户端的应用
  • JS 面试题总结
  • JS+CSS实现数字滚动
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • spring boot下thymeleaf全局静态变量配置
  • 翻译--Thinking in React
  • 回顾 Swift 多平台移植进度 #2
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 码农张的Bug人生 - 见面之礼
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 推荐一个React的管理后台框架
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #{}和${}的区别是什么 -- java面试
  • #考研#计算机文化知识1(局域网及网络互联)
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转)使用VMware vSphere标准交换机设置网络连接
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .net 按比例显示图片的缩略图
  • .Net的DataSet直接与SQL2005交互
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .net实现客户区延伸至至非客户区
  • .NET应用架构设计:原则、模式与实践 目录预览
  • .NET中的十进制浮点类型,徐汇区网站设计
  • @synthesize和@dynamic分别有什么作用?