Node编写用户登录接口

news2024/12/29 5:05:29

目录

前言

服务器

编写登录接口API

使用sql语句查询数据库中是否有该用户

判断密码是否正确

生成JWT的Token字符串

配置解析token的中间件

配置捕获错误中间件

完整的登录接口代码


前言

本文介绍如何使用node编写登录接口以及解密生成token,如何编写注册接口已经在Node编写用户注册接口这篇文章中介绍,本文是建立在编写注册接口这篇文章的基础之上

同时也可以在在前端html页面中向服务器发送post登录请求这篇文章中了解登录请求

服务器

关于创建服务器,本文中和Node编写用户注册接口共用一个服务器,已经引入了router对象

// 导入express模块
const express = require('express')

// 创建express服务器实例
const app = express()

// 导入跨域cors
const cors = require('cors')

// 全局挂载
app.use(cors())

// 配置解析表单数据中间件
app.use(express.urlencoded({extended:false}))

// 导入用户路由对象
const userRouter = require('./router/user')
app.use('/api',userRouter)

// 启动服务器
app.listen(3007,()=> {
    console.log('running the http://127.0.0.1:3007');
})

编写登录接口API

使用sql语句查询数据库中是否有该用户
const userinfo = req.body
    const sql = 'select * from ev_users where username = ?'
    db.query(sql, userinfo.username, function (err, results) {
        // 执行 SQL 语句失败
        if (err) {
            return res.send({status:1,message:err.message})
        }
        // 执行 SQL 语句成功,但是查询到数据条数不等于 1
        if (results.length !== 1) {
            return res.send({status:1,message:'登录失败'})
        }
        res.send('登录成功')
    })

使用postman模拟发送登录请求,查询是否有用户名为b

返回登录成功

数据库中有b用户

如果未注册

数据库中没有c用户

判断密码是否正确

调用了bcrypt.compareSync()方法,用来解密,因为在注册时已经把密码加密了,所以需要解密

bcrypt.compareSync(用户提交的密码,数据库中的密码)

// 判断密码是否正确
        const compareResult = bcrypt.compareSync(userinfo.password,results[0].password)
        if(!compareResult) return res.send({status:1,message:'密码错误'})
        res.send('登录成功')

验证b的密码是否正确

b的密码是000000

当把b的密码换成111111时,也就是错误密码

返回密码错误

生成JWT的Token字符串

关于JWT认证,可以浏览JWT认证这篇文章

生成token字符串时,要把密码和用户头像剔除,因为生成的token会保留在浏览器中,很容易泄露

// 剔除完毕之后,user 中只保留了用户的 id, username, nickname, email 这四个属性的值
const user = { ...results[0], password: '', user_pic: '' }

先安装jsonwebtoken

npm i jsonwebtoken

导入jwt

const jwt = require('jsonwebtoken')

导入成功后调用jwt.sign()生成JWT字符串

jwt.sign(用户的信息,加密的密钥,配置对象有效token的时间)

// 生成 Token 字符串
        const tokenStr = jwt.sign(user, jwtSecreKey, {
        expiresIn: '10h', // token 有效期为 10 个小时
            })

将生成的token字符串发送给客户端

在生成的的token字符串前拼接上"Bearer",固定用法

res.send({
                status: 0,
                message: '登录成功!',
                // 为了方便客户端使用 Token,在服务器端直接拼接上 Bearer 的前缀
                token: 'Bearer ' + tokenStr,
              })

使用postman模拟发送请求

配置解析token的中间件

将jwt字符串还原为JSON对象,在get请求时,可以获得用户信息

安装express-jwt

npm i express-jwt

导入

/ 导入解析token字符串
const exoressjwt = require('express-jwt')

解析token

// 使用 .unless({ path: [/^\/api\//] }) 指定哪些接口不需要进行 Token 的身份认证
app.use(expressjwt.expressjwt({
    secret:jwtSecreKey,
    algorithms:['HS256'],
}).unless({path:[/^\/api\//]}))
配置捕获错误中间件
// 错误中间件
app.use(function (err, req, res, next) {
    // 数据验证失败
    if (err instanceof joi.ValidationError) return res.send({status:1,message:err.message})
    // 捕获身份认证失败的错误
   if (err.name === 'UnauthorizedError') return res.send({satus:1,message:'身份认证失败'})
    // 未知错误
    res.send({status:1,message:err.message})
  })

完整的登录接口代码

// 导入express模块
const express = require('express')
// 导入数据库对象
const db = require('../db/index')

// 导入加密模块
const bcrypt = require('bcryptjs')

// 创建路由对象
const router = express.Router()

// 导入JWT
const jwt = require('jsonwebtoken')
// 定义密钥
const jwtSecreKey = 'notbald'


// 登录接口
router.post('/login',(req,res)=>{
    const userinfo = req.body
    const sql = 'select * from ev_users where username = ?'
    db.query(sql, userinfo.username, function (err, results) {
        // 执行 SQL 语句失败
        if (err) {
            return res.send({status:1,message:err.message})
        }
        // 执行 SQL 语句成功,但是查询到数据条数不等于 1
        if (results.length !== 1) {
            return res.send({status:1,message:'登录失败'})
        }
        // 判断密码是否正确
        const compareResult = bcrypt.compareSync(userinfo.password,results[0].password)
        if(!compareResult) return res.send({status:1,message:'密码错误'})
        // 生成token字符串,展开运算符,剔除密码和用户头像
        const user = {...results[0],password:'',user_pic:''}
        // console.log(user);
        
        // 生成 Token 字符串
        const tokenStr = jwt.sign(user, jwtSecreKey, {
        expiresIn: '10h', // token 有效期为 10 个小时
            })
            
            res.send({
                status: 0,
                message: '登录成功!',
                // 为了方便客户端使用 Token,在服务器端直接拼接上 Bearer 的前缀
                token: 'Bearer ' + tokenStr,
              })
    })
})

解析token以及全局捕获错误中间件在服务器中

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

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

相关文章

侯捷C++面向对象程序设计笔记(上)-Object Based(基于对象)部分

基于对象就是对于单一class的设计。 对于有指针的:complex.h complex-test.cpp 对于没有指针的: string.h string-test.cpp https://blog.csdn.net/ncepu_Chen/article/details/113843775?spm1001.2014.3001.5501#commentBox 没有指针成员——以复数co…

【单片机学习笔记】Windows+Vscode+STM32F4+freeRTOS+FatFs gcc环境搭建

为摒弃在接受keil邮件,研究了下gun编译,以STM32F407为例,简单记录 1. 软件包准备 Git 选择对应版本直接安装即可https://git-scm.com/download/winmakegcc ​ 1)将上述软件包放置于C盘根目录 2)添加环境变量 3&am…

分类预测 | MATLAB实现SSA-CNN-BiLSTM-Attention数据分类预测(SE注意力机制)

分类预测 | MATLAB实现SSA-CNN-BiLSTM-Attention数据分类预测(SE注意力机制) 目录 分类预测 | MATLAB实现SSA-CNN-BiLSTM-Attention数据分类预测(SE注意力机制)分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.MAT…

Android View拖拽startDragAndDrop,Kotlin

Android View拖拽startDragAndDrop,Kotlin import android.os.Bundle import android.util.Log import android.view.DragEvent import android.view.View import android.view.View.OnDragListener import android.view.View.OnLongClickListener import android.w…

Spring中方法拦截器

一、MethodInterceptor 在动态代理中要想添加一个额外功能,只要去实现MethodBeforeAdvice这个接口就行了,但是实现了这个接口的额外功能只能运行在目标类执行之前,如果是想在目标类执行之后呢?那这个需求就完成不了,所…

SpringBoot Lombok的使用

目录 下载Lombok插件 Lombok的用法 获取日志对象 生成get,set方法 Lombok框架的实现原理 Lombok的常用注解 下载Lombok插件 要使用Lombok首先要确保idea安装了lombok插件 在项目中添加 lombok依赖 在<dependency>里右键生成点击edit starters 插件(没有就下载,可…

行业模型应该如何去拆解?

行业模型应该如何去拆解&#xff1f; 拆解行业模型是一个复杂的过程&#xff0c;涉及对整个行业的深入分析和理解。下面是一些步骤和方法&#xff0c;可以帮助你系统地拆解行业模型&#xff1a; 1. 确定行业范围 定义行业&#xff1a;明确你要分析的行业是什么&#xff0c;包括…

寻找二叉树一个节点的后继节点

后继节点&#xff1a;中序遍历的后一个节点 普通二叉树&#xff1a;中序遍历得到一个list&#xff0c;时间复杂度O(n) 本题的二叉树&#xff1a;有父节点的指针&#xff0c;后继节点与原节点的距离为1&#xff0c;因此可以直接通过父节点找到下一个节点 优化&#xff1a;节点…

出差学小白知识No6:LD_PRELOAD变量路径不对找不到库文件

交叉编译的时候出现以下问题&#xff0c;显示LD_PRELOAD变量找不到路劲 首先先查看一下LD_PRELOAD的路径&#xff1a;echo $LD_PRELOAD 如果输出一大串&#xff0c;那么先进行清空&#xff1a;unset LD_PRELOAD 重新给LD_PRELOAD进行赋值他的路径和库文件&#xff1a; expor…

亚马逊、eBay、wish、Lazada、shoppe和mercari如何降低测评成本提高测评效率?

测评&#xff08;补单&#xff09;是跨境卖家在如亚马逊、Lazada、Shopee、wish、eBay、速卖通、阿里国际、沃尔玛、newegg、mercari等平台运营中不可或缺的需求。近年来&#xff0c;测评技巧在跨境卖家圈中越来越活跃。那么为什么跨境测评对于亚马逊卖家来说如此重要呢&#x…

【Leetcode】 213. 打家劫舍 II ?

你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈&#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚…

Java反射实体组装SQL

之前在LIS.Core定义了实体特性&#xff0c;在LIS.Model给实体类加了表特性&#xff0c;属性特性&#xff0c;外键特性等。ORM要实现增删改查和查带外键的父表信息就需要解析Model的特性和实体信息组装SQL来供数据库驱动实现增删改查功能。 实现实体得到SQL的工具类&#xff0c…

视觉SLAM十四讲-第三讲三维刚体运动

什么是刚体运动以及三维空间中刚体运动描述方式有哪些&#xff1f; 两个坐标系之间的运动由一个旋转加上一个平移组成&#xff0c;这种运动称为刚体运动。描述三维空间中刚体运动的方式有旋转矩阵、旋转向量、欧拉角、四元数。 请描述左手坐标系和右手坐标系。 大拇指——y …

筹备三年,自动驾驶L3标准将至,智驾产业链的关键一跃

‍作者|张祥威 编辑|德新 多位知情人士告诉HiEV&#xff0c;智能网联汽车准入试点通知&#xff0c;乐观预计将在一个月内发布。试点的推动&#xff0c;意味着国家层面的自动驾驶L3标准随之到来。 「L3标准内容大部分与主机厂相关&#xff0c;由工信部牵头&#xff0c;找了几家…

电子企业MES管理系统体系架构与功能解析

随着科技的不断发展&#xff0c;电子企业对于生产过程的数字化需求日益增强。为了满足这一需求&#xff0c;许多企业开始引入MES&#xff08;制造执行系统&#xff09;来打造数字化车间&#xff0c;以改善车间的管理和生产等各环节。本文将详细介绍电子企业MES系统的体系架构和…

pythonselenium自动化测试实战项目

说明&#xff1a;本项目采用流程控制思想&#xff0c;未引用unittest&pytest等单元测试框架 一.项目介绍 目的 测试某官方网站登录功能模块可以正常使用 用例 1.输入格式正确的用户名和正确的密码&#xff0c;验证是否登录成功&#xff1b; 2.输入格式正确的用户名和不…

echarts 实现双Y轴刻度对齐

话不多说&#xff0c;直接上代码&#xff1a; min: min2, max: max2, splitNumber: 5, interval: (max2 - min2) / 5, const min1 this._getMinValue(dataArr1),min2 this._getMinValue(dataArr2),max1 this._getMaxValue(dataArr1),max2 this._getMaxValue(dataArr2); _g…

微信小程序授权登录--流程讲解

一、微信授权登录流程 小程序登录 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识&#xff0c;快速建立小程序内的用户体系。 步骤流程&#xff1a; 1.小程序调用wx.login() 获取 临时登录凭证code &#xff0c;并回传到开发者服务器 2.开发者服务…

机器学习---CNN(创建和训练一个卷积神经网络并评估其性能)下

import numpy as np import matplotlib.pyplot as plt from cnn_operations import cnn_operations as cnn_opr convolutional_neural_network模块&#xff1a; 1. 卷积神经网络类 def __init__(self):# 网络的层数self.n_layers 0# list&#xff0c;网络中的各层self.layers…

v-for列表渲染

一、v-for迭代数组 <li v-for"(e,index) in emp" :key"e.id">编号{{index1}} 名字{{e.name}} 年龄{{e.age}} </li> e 是循环数组中的每个元素的别名index 是当前循环的下表&#xff0c;从0开始:key 的作用&#xff1a; 是为了给 Vue 一个提示…