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

news2024/11/17 0:05:28

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或false
      const 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'],
  })
)

效果展示

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

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

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

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

相关文章

毫无基础的人如何入门 Python ?--找对学习入口是关键!

1.行百里者半三十 不少学生或职场人士总面临这样一种窘境:数字化转型大背景、大趋势下,感觉非常有必要学习Python等分析工具,但在真正学习Python的各种语言规则时,往往体验不到知识的乐趣,翻看个别章节后即束之高阁。…

循环神经网络RNN

1. 背景 RNN(Recurrent Neural Networks) CNN利用输入中的空间几何结构信息;RNN利用输入数据的序列化特性。 2. SimpleRNN单元 传统多层感知机网络假设所有的输入数据之间相互独立,但这对于序列化数据是不成立的。RNN单元用隐藏状态或记忆引入这种依赖…

力扣 --- 三数之和

目录 题目描述: 思路描述: 代码: 提交结果: 官方代码: 官方提交结果: 题目描述: 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k…

【虚拟机】Docker基础 【二】

2.2.数据卷 容器是隔离环境,容器内程序的文件、配置、运行时产生的容器都在容器内部,我们要读写容器内的文件非常不方便。大家思考几个问题: 如果要升级MySQL版本,需要销毁旧容器,那么数据岂不是跟着被销毁了&#x…

vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?

面试官:vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做? 一、是什么 权限是对特定资源的访问许可,所谓权限控制,也就是确保用户只能访问到被分配的资源 而前端权限归根结底是请求的发起权,请求…

上海震坤行被评为虹桥生产线互联网服务高质量发展平台

上海震坤行被评为虹桥生产线互联网服务高质量发展平台 10月12日,新一期“潮涌浦江投资虹桥”活动暨“战略赋能新机遇,开放引领新高地”——2023虹桥国际中央商务区投资促进大会在上海虹桥举行。 本次活动旨在释放关于推动虹桥国际开放枢纽进一步提升能级…

Attention机制(笔记)

参考:2.3.2注意力机制-part1_哔哩哔哩_bilibili 什么是attention? 答:注意力放在事物最有辨识度的部分 attention计算机制: 为什么用这个公式可以得到attention? 补充说明(chatGPT给出的解释)&…

Vue中 实现自定义指令(directive)及应用场景

一、Vue2 1. 指令钩子函数 一个指令定义对象可以提供如下几个钩子函数 (均为可选): bind 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已…

高等数学中微分方程的种类及其解法

1 微分方程的基本概念 1.1 微分方程 含导数或微分的方程,称为微分方程 1.2 微分方程的阶 微分方程中所含的导数或微分的最高阶数,称为该微分方程的阶数 1.3 微分方程的解 使得微分方程成立的函数,称为微分方程的解,微分方程的解可分为通解和特解 不含任意常数的微分方程的…

正式确定,奥特曼重回 OpenAI 担任 CEO

今天,OpenAI 正式宣布山姆奥特曼回归 OpenAI,重新担任 CEO: 米拉将回归首席技术官职位(CTO)而新的初步董事会成员包括布雷特泰勒(主席)、拉里萨默斯和亚当D’安杰洛。经此一役,可以…

Java核心知识点整理大全23-笔记

目录 21. JAVA 算法 21.1.1. 二分查找 21.1.2.冒泡排序算法 21.1.3. 插入排序算法 21.1.4. 快速排序算法 21.1.1. 希尔排序算法 21.1.2. 归并排序算法 21.1.3. 桶排序算法 21.1.4. 基数排序算法 21.1.5. 剪枝算法 21.1.6. 回溯算法 21.1.7. 最短路径算法 21.1.8. 最…

用java实现拼图小游戏

1、了解拼图游戏基本功能: 拼图游戏内容由若干小图像块组成的,通过鼠标点击图像块上下左右移动,完成图像的拼凑。 2、拼图游戏交互界面设计与开发: 通过创建窗体类、菜单、中间面板和左右面板完成设计拼图的交互界面 &#xff…

请大数据把奥威BI分析工具推给每一个财务!

这个财务指标怎么算?那些数据什么时候能拿到?看完报表,发现某部门上个月的支出涨幅过大,想了解原因怎么办?……财务人,你是不是每个月都把时间消耗在这些事情上了?那你可得快接住这个BI大数据分…

ROM和RAM概念

一、存储器特性 1)易失性:掉电数据会丢失,通常指RAM; RAM分为SRAM、DRAM SRAM:静态RAM,只要上电数据就不会丢失; DRAM:动态RAM,需要每隔一段事件刷新数据,否…

基于安卓的2048益智游戏的设计与实现

基于安卓的2048益智类游戏的设计与实现 摘要:现如今随着社会日新月异,人们越来越离不开智能手机所提供的灵活性与便携性。安卓系统是在这股手机发展迅猛的潮流中其市场占有率过半的手机平台,基于安卓系统的游戏开发有着不可估量的前景。 本论…

CSS特效022:小球抛物线效果

CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧,主要包含CSS布局,CSS特效,CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点,CSS特效主要是一些动画示例,CSS花边是描述了一些CSS…

中国版的 GPTs:InsCode AI 生成应用

前言 在上一篇文章 《InsCode:这可能是下一代应用开发平台?》中,我们介绍了一个新的应用开发平台 InsCode,它是基于云原生开发环境 云 IDE AI 辅助编程的一站式在线开发平台。 最近,InsCode 又推出了另一种全新的开…

科研学习|论文解读——Task complexity and difficulty in music information retrieval

摘要: 关于音乐信息检索(MIR)中任务复杂度和任务难度的研究很少,而文本检索领域的许多研究发现任务复杂度和任务难度对用户效率有显着影响。本研究旨在通过探索 i) 任务复杂度和任务难度之间的关系; ii) 影响任务难度的…

Linux系统的常见命令十,打包以及解包、链接(tar、ln)

目录 tar命令ln命令 本文主要介绍Linux系统的打包以及解包、链接命令tar、ln。 gzip 和bzip2只能压缩文件,但是不能压缩目录。而zip可以压缩文件也可以压缩目录但是解压过后内容全部都丢失了。打包就是把一些零零散散的东西全部都堆到一起。 tar命令 tar&#xff…

如何运用智能安全帽、执法记录仪等技术手段提高隧道施工人员定位和安全监管效率?

应用需求 隧道中通常没有4G网络,无法搜到GPS卫星, 而领导从安全生产监管的角度,又需要看到现场的视频、录像、人员定位等。这正是本方案需要解决的问题。 系统特点 在无网络的隧道内部录像,紧急情况可派人出隧道,把…