express实现用户登录和注册接口

目录

  • 1 创建数据库
  • 2 连接数据库
  • 3 集成ORM库
  • 4 创建业务逻辑
  • 5 创建路由
  • 7 测试接口
  • 总结

我们在编写后端接口的时候操作数据库是一种常见的功能需求,express本身并不提供直接操作数据库的能力,需要借助第三方库来操作数据库,本篇讲解一下软件开发中像登录和注册如何实现。

1 创建数据库

通常我们编制软件的时候需要选择数据库,我这里选择mysql作为示例,如果你有比较喜欢的数据库也可以按照相同的操作进行。

安装数据库可以参考网上的教程,因为比较普遍这里就不赘述了。数据库安装好之后,用数据库的连接工具来操作数据,我这里用的是navicate,你也可以用别的。

打开我们的navicate,点击连接
在这里插入图片描述
选择mysql
在这里插入图片描述
输入连接名,因为我数据库是在本地,直接输入localhost就行,然后输入数据库的用户名和密码,点击测试连接
在这里插入图片描述
然后点击你的连接名,右键,点击新建数据库
在这里插入图片描述
输入数据库的名称,字符集选择utf8mb4,排序规则选择第一项就可以
在这里插入图片描述
双击数据库名称,选择表,点击新建表
在这里插入图片描述
创建四个字段,分别是username、password、email、id,前三个选择varchar类型就可以,第四个字段需要作为主键,勾选自动增长
在这里插入图片描述
然后点击保存按钮,输入表名即可
在这里插入图片描述
除了可视化的建表外,我们还可以使用sql语句来建表,以下是建表语句

CREATE TABLE users (  
    id INT AUTO_INCREMENT PRIMARY KEY,  
    username VARCHAR(50) NOT NULL UNIQUE,  
    password VARCHAR(255) NOT NULL,  
    email VARCHAR(100) NOT NULL UNIQUE,  
    createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,  
    updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP  
);

还是在navicate里,点击查询、新建查询,输入我们的建表语句
在这里插入图片描述
在这里插入图片描述
点击运行,看到输出的OK就表示表已经创建成功了

2 连接数据库

连接数据库通常需要配置数据库的IP、用户名和密码,我们创建一个环境变量的配置文件来存储这些信息,打开我们的工程,在根目录下创建一个.env的文件
在这里插入图片描述
贴入如下配置

DATABASE_NAME=express  
DATABASE_USER=root  
DATABASE_PASSWORD=111111  
DATABASE_HOST=localhost

具体的配置信息要改成你自己设定的数据库的信息

然后在app.js中读取我们的配置

require('dotenv').config();//加载环境变量

我们使用了dotenv的库,需要先进行安装

npm install dotenv

在这里插入图片描述
完成上述步骤你就可以看到我们的配置信息被正确的读取到了

3 集成ORM库

我们这里使用sequelize来做数据库的操作,orm的好处可以屏蔽具体的数据库语句的细节,在操作数据库的时候可以使用他封装好的API,省了不少事。而且后期如果你想切换数据库,改一下配置文件就可以了。

在项目的根目录创建一个config文件夹,里边创建一个database.js
在这里插入图片描述
贴入如下的配置信息

// 导入 Sequelize 和相应的数据库驱动  
const { Sequelize } = require('sequelize');  
const sequelize = new Sequelize(process.env.DATABASE_NAME, process.env.DATABASE_USER, process.env.DATABASE_PASSWORD, {  
  host: 'localhost',  
  dialect: 'mysql', // 根据你的数据库类型选择 'mysql' | 'mariadb' | 'postgres' | 'mssql' | 'sqlite' | 'postgres-native' | 'mariadb-native'  
  // 其他可能的配置选项  
  dialectOptions: {  
    useUTC: true, // 对于不支持 UTC 的数据库,启用这个选项  
    // 针对特定数据库的额外配置,比如 SSL  
  },  
  pool: {  
    max: 5, // 连接池中的最大连接数  
    min: 0, // 连接池中的最小连接数  
    acquire: 30000, // 连接最大等待时间(毫秒)  
    idle: 10000 // 连接在释放之前可以空闲的最长时间(毫秒)  
  },  
  // 其他的 Sequelize 配置项...  
  logging: console.log, // 启用日志,你可以选择自己的日志函数或者禁用它  
});  
  
// 测试连接  
sequelize  
  .authenticate()  
  .then(() => {  
    console.log('Connection has been established successfully.');  
  })  
  .catch(err => {  
    console.error('Unable to connect to the database:', err);  
  });  
  
// 导出 Sequelize 实例供其他模块使用  
module.exports = sequelize;

添加配置信息后我们先需要按照库,执行如下命令

npm install sequelize
npm install mysql2

配置创建好之后,需要创建模型层,新建一个model文件夹,里边创建一个User.js
在这里插入图片描述
输入如下配置

// models/User.js  
const { Sequelize, Model } = require('sequelize');  
const sequelize = require('../config/database'); // 假设你有一个数据库配置文件  
  
class User extends Model {}  
  
User.init(  
  {  
    email: {  
      type: Sequelize.STRING,  
      unique: true,  
      allowNull: false,  
    },  
    password: {  
      type: Sequelize.STRING,  
      allowNull: false,  
    }, 
    username: {
        type:Sequelize.STRING,
        allowNull: false, 
    } 
    // 其他字段...  
  },  
  {  
    sequelize,  
    modelName: 'User',  
  }  
);  
  
module.exports = User;

如果你的模型和表名不一致,需要指定表名,我这里使用了默认的推断机制,他会转换为小写加一个s的后缀去匹配表,正好是我们的users表

4 创建业务逻辑

我们把业务逻辑封装到service层,这样代码的维护性要好一点,在根目录创建services文件夹,创建一个authService.js

// services/authService.js  
const bcrypt = require('bcrypt');  
const jwt = require('jsonwebtoken');  
const User = require('../models/User');  
  
class AuthService {  
  async signUp(username, password,email) {  
    console.log(username,password,email)
    const salt = await bcrypt.genSalt(10);  
    const hashedPassword = await bcrypt.hash(password, salt);  
    const user = await User.create({ username,email, password: hashedPassword });  
    return user;  
  }  
  
  async signIn(username, password) {  
    const user = await User.findOne({ where: { username } });  
    if (!user) throw new Error('User not found');  
    const isMatch = await bcrypt.compare(password, user.password); 
    console.log("isMatch",isMatch) 
    if (!isMatch) throw new Error('Invalid credentials');  
    const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET_KEY, { expiresIn: '1h' });  
    return { user, token };  
  }  
}  
  
module.exports = AuthService;

这里我们写了两个方法,一个是注册,注册的时候需要给密码加密,登录的时候需要返回给用户一个token,需要安装需要的第三方的库

npm install bcrypt jsonwebtoken

因为我们在创建token时候需要一个密钥,我们也在配置信息里添加,在.env里增加密钥

JWT_SECRET_KEY=d6b522d9a989a9ff8494676b4e1592ea58488b8a4f8126d33d331604e769f4d3

5 创建路由

一切准备就绪之后最后一步就是创建路由了,我们在根目录创建routes,然后创建auth.js
在这里插入图片描述
输入如下代码

// routes/auth.js  
const express = require('express');  
const router = express.Router();  
const AuthService = require('../services/authService');  
const authService = new AuthService();  
// 登录路由  
router.post('/signIn', async (req, res, next) => {  
  try {  
    const { username, password } = req.body;  
    console.log(username,password)
    
    
    console.log(authService)
    const { user, token } = await authService.signIn(username, password);  
    res.cookie('token', token, { httpOnly: true, secure: true }); // 假设使用cookie存储token  
    return res.status(200).json({ code:200,data:{token:token},message:'login success' });  
  } catch (error) { 
    console.log('error',error.message) 
    if (error.message === 'Invalid credentials'||error.message ==='User not found') {  
        // 如果是因为无效的凭证,返回401状态码  
        res.status(401).json({ code:401,message: 'Invalid credentials' });  
      } else {  
        // 其他错误,返回500状态码  
        res.status(500).json({ code:500,message: 'Internal server error' });  
        // 可能还需要记录错误日志  
      }  
    //next(error);  
  }  
});  
  
// 注册路由  
router.post('/signUp', async (req, res, next) => {  
  try {  
    const { username, password ,email} = req.body;  
    const user = await authService.signUp(username,password,email);  
    res.status(200).json({code:200,id:user.id});  
  } catch (error) {  
    //next(error);
    res.status(500).json({ code:500,message: 'Internal server error' });   
  }  
});  
  


module.exports = router;

我们的路由创建好之后要挂载到应用程序里,修改app.js增加路由的挂载代码

const authRouter = require('./routes/auth')//引入权限接口路由
app.use('/api/auth', authRouter);//挂载权限路由

因为接口涉及到参数解析,我们还要启用解析的中间件

// 对于 JSON 请求体  
app.use(express.json());  
  
// 对于 URL 编码的请求体  
app.use(express.urlencoded({ extended: true }));

7 测试接口

接口开发完毕后,就可以进行测试了,这里使用Postman来测试,先测试一下注册接口
在这里插入图片描述
然后再测试一下登录接口
在这里插入图片描述
可以看到两个接口都已经正常返回数据,这样就可以了

总结

本篇我们讲解了一下用户登录和注册接口的开发,涉及到环境变量的初始化,Orm库的搭建以及路由的配置,熟悉了整套流程,后续的功能开发就可以按照自己的需求完成了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java】LinkedList模拟实现

目录 整体框架IMyLinkedList接口IndexNotLegalException异常类MyLinkedList类成员变量(节点信息)addFirst(头插)addLast(尾插)在指定位置插入数据判断是否存在移除第一个相等的节点移除所有相等的节点链表的长度打印链表释放回收链表 整体框架 IMyLinkedList接口 这个接口用来…

2006-2023年2月各地级市城投债详细数据

2006-2023.2各地级市城投债详细数据 1、时间:2006-2023.2 2、来源:深圳证券交易所和上海证券交易所官网、人民银行、证券监督管理委员会等金融监管机构等官网 3、指标:省份、城市、证券代码、证券简称、债券简称、证券全称、债券初始面值单…

C语言使用STM32开发板手搓高端家居洗衣机

目录 概要 成品效果 背景概述 1.开发环境 2.主要传感器。 技术细节 1. 用户如何知道选择了何种功能 2.启动后如何进行洗衣 3.如何将洗衣机状态上传至服务器并通过APP查看 4.洗衣过程、可燃气检测、OLED屏显示、服务器通信如何并发进行 小结 概要 本文章主要是讲解如…

使用pdf表单域填充pdf内容

需要引用如下包 <dependency><groupId>com.itextpdf</groupId><artifactId>itext-core</artifactId><version>8.0.3</version><type>pom</type></dependency>1、预先准备一个pdf模板&#xff0c;并在指定位置添加…

创建一个vue3 + ts + vite 项目

vite 官网&#xff1a; https://cn.vitejs.dev/guide/ 兼容性注意 Vite 需要 Node.js 版本 18&#xff0c;20。然而&#xff0c;有些模板需要依赖更高的 Node 版本才能正常运行&#xff0c;当你的包管理器发出警告时&#xff0c;请注意升级你的 Node 版本。 安装项目 1. 使用n…

政安晨:【Keras机器学习实践要点】(五)—— 通过子类化创建新层和模型

目录 介绍 安装 层级&#xff1a;状态&#xff08;权重&#xff09;与某些计算的组合 层可以有不可训练的重量 最佳实践&#xff1a;推迟权重的创建&#xff0c;直到输入的形状已知。 层可以递归组合 后端不可知层和特定后端层 add_loss()方法 可以选择在您的层上启用…

【DETR系列目标检测算法代码精讲】01 DETR算法01 DETR算法框架和网络结构介绍

为什么要有DETR 总所周知&#xff0c;传统的目标检测算法非常依赖于anchor和nms等手工设计操作&#xff0c;非常费时费力&#xff0c;自然而然的就产生了取消这些操作的想法。但是我们首先需要思考的是&#xff0c;为什么我们需要anchor和nms&#xff1f; 因为我们是没有指定…

3D汽车模型线上三维互动展示提供视觉盛宴

VR全景虚拟看车软件正在引领汽车展览行业迈向一个全新的时代&#xff0c;它不仅颠覆了传统展览的局限&#xff0c;还为参展者提供了前所未有的高效、便捷和互动体验。借助于尖端的vr虚拟现实技术、逼真的web3d开发、先进的云计算能力以及强大的大数据处理&#xff0c;这一在线展…

Docker Swarm安装部署应用

一、Docker Swarm核心概念 1、什么是Docker Swarm GitHub地址 Docker Swarm 是 Docker 官方推出的容器集群管理工具&#xff0c;基于 Go 语言实现。使用它可以将多个 Docker 主机封装为单个大型的虚拟 Docker 主机&#xff0c;快速打造一套容器云平台。 Docker Swarm 是生产…

Java线程池工作原理浅析

为什么要用线程池&#xff1f; 1、线程属于稀缺资源&#xff0c;它的创建会消耗大量系统资源 2、线程频繁地销毁&#xff0c;会频繁地触发GC机制&#xff0c;使系统性能降低 3、多线程并发执行缺乏统一的管理与监控 线程池的使用 线程池的创建使用可通过Executors类来完成…

【网站项目】泉文化管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Vue2(十二):Vuex环境搭建、Vuex工作原理、几个配置项、多组件共享数据、Vuex模块化

一、Vuex 1.概念 专门在Vue中实现集中式状态&#xff08;数据&#xff09;管理的一个Vue插件&#xff08;use引入&#xff09;&#xff0c;对vue应用中多个组件的共享状态进行集中式的管理&#xff08;读&#xff0f;写&#xff09;&#xff0c;也是一种组件间通信的方式&…

String,StringBuffer,StringBuilder 的区别【大白话Java面试题】

String&#xff0c;StringBuffer&#xff0c;StringBuilder 的区别【大白话Java面试题】 大白话回答 1、可变/不可变类 String是不可变类。他被被final修饰&#xff0c;所以每一次的创建修改删除都要重新分配内存创建新的对象。 StringBuilder和StringBuffer是可变类&#xff…

Linux部署Sonarqube+Gogs+Jenkins(一)

Linux部署SonarqubeGogsJenkins 一、1.Linux安装JDK11环境1. 本地进行上传2. 进入到/usr/java目录&#xff0c;并且进行解压3. 配置文件/etc/profile&#xff0c;配置环境变量4.让对应的配置文件生效5. 验证 二、Linux安装Python环境三、Linux安装Jenkins环境1、/usr目录下创建…

ssm框架笔记-maven

html是骨头 css使皮肤 js是你能做的动作 MAVEN 依赖管理&#xff1a;1.声明dependenciys标签 2.maven search3。 版本号提取 3.$引用 3.2依赖传递和冲突 依赖传递指的是当一个模块或库 A 依赖于另一个模块或库 B&#xff0c;而 B 又依赖于模块或库 C&#xff0c;那么 A 会间…

ADT 创建表,并用ABAP往里面插数据

参考&#xff1a;Create Table Persistence and Generate Data | SAP Tutorials 4、Replace your code with following: CLASS zcl_generate_travel_data_xxx DEFINITIONPUBLICFINALCREATE PUBLIC .PUBLIC SECTION.INTERFACES if_oo_adt_classrun.PROTECTED SECTION.PRIVATE S…

基于SSM医院病历管理系统

基于SSM医院病历管理系统的设计与实现 摘要 病历管理系统是医院管理系统的重要组成,在计算机技术快速发展之前&#xff0c;病人或者医生如果想记录并查看自己的健康信息是非常麻烦的&#xff0c;因为在以往病人的健康信息通常只保存在自己的病历卡或者就诊报告中&#xff0c;…

【C++】vector的介绍及使用说明(类模版的实现方式,顺序存储与动态数组,迭代器iterator的运用,vector的增删查改)

目录 00.引言 01.vector的介绍 类模版 动态分配内存 顺序存储 02.vector的使用 构造函数 迭代器iterator 1.分类&#xff1a; 2.运用&#xff1a; 扩容 1.resize() 2.reverse() 增删查改 1.增加 2.删除 3.查找 4.修改 00.引言 以前我们讲过string类&#xff0…

如何系统的自学python?

系统地自学Python是一个循序渐进的过程&#xff0c;以下是一份详细的指南&#xff0c;帮助你从零开始逐步掌握这门语言&#xff1a; 1、了解Python及其应用场景&#xff1a; 阅读关于Python的简介&#xff0c;理解它为何流行&#xff0c;以及在哪些领域&#xff08;如Web开发…

stream流中的坑,peek/map/filter

起因 所在系统为一个对账系统&#xff0c;涉及的业务为发布账单&#xff0c;数据结构定的是供应商账单发布&#xff0c;生成企业账单和个人账单。发布账单处理完本系统业务后&#xff0c;需要生成站内通知和调用外部接口生成短信通知。后来增加需求&#xff0c;需要在发布完成…