【Node.js】使用 PostgreSQL、Sequelize 和 Express.js 进行 Node.js 认证

使用 PostgreSQL、Sequelize 和 Express.js 进行 Node.js 认证
作者:Racheal Kuranchie
来源:https://medium.com/@rachealkuranchie/node-js-authentication-with-postgresql-sequelize-and-express-js-20ae773da4c9


使用 PostgreSQL、Sequelize 和 Express.js 进行 Node.js 认证

使用 JSON Web Token(JWT)和 Cookie-Parser 进行用户认证

在本文中,我们将讨论用户注册和登录,通过使用 PostgreSQL 作为数据库、Sequelize 作为对象关系映射器(ORM),以及 Express.js 作为服务器,结合 Cookie-Parser 设置 cookie 和 JSON Web Token(JWT)。

理解概念

用户注册是应用程序中的一个相关步骤,因此涉及到认证和授权的概念。认证和授权是出于安全目的的要求。

这两个概念经常交替使用,这使得难以区分你想要实现的功能以及它所需的内容。

在我们深入认证之前,让我们澄清这两个概念之间的区别。认证是确定用户是否是他们声称的那个人。通过这一点,它检查数据库以查看用户的凭据是否与数据库中授权用户的凭据匹配。相比之下,授权指定数据用户可以访问你的应用程序。

Cookies 是在请求中发送到 Web 浏览器的小数据片段。它们作为键值对存储在 Web 浏览器中。键作为给特定 cookie 命名的名称。值表示所需的特定数据。Cookies 在大多数应用程序中都是必不可少的。例如,cookies 可以保持用户登录到你的应用程序。对于这个应用程序,我们将使用 Cookie-Parser 和 JSON Web Token 生成一个令牌,用作 cookie 的值。

示例 cookie — admin: ydfgyfgeuygfegyfgirgcfygfyhgcyg

JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式来安全地传输信息并在各方之间作为 JSON 对象传递。JWT 由三个由点分隔的部分构成,即头部、负载和签名。负载特性允许我们使用用户 ID 和密钥生成令牌,这使得它更适合用于为特定用户设置 cookie。

目录
  • 第 1 步:创建 Node Express 项目
  • 第 2 步:数据库和服务器配置
  • 第 3 步:设置用户模式
  • 第 4 步:中间件设置
  • 第 5 步:设置环境变量
  • 第 6 步:设置控制器
  • 第 7 步:配置 Express 路由器
  • 第 8 步:重构服务器
  • 第 9 步:测试
先决条件

首先,你必须安装以下软件:

  • Node => 下载链接
  • PostgreSQL & pgAdmin => 下载链接
第 1 步:创建 Node Express 项目

通过以下命令创建项目文件夹:

mkdir backend
cd backend

现在,使用以下命令创建 package.json 文件:

npm init -y

NB: 参考 Sequelize 文档 => 文档链接

接下来,安装这些包:

  • Express — Node.js 框架 npm install express
  • Sequelize — PostgreSQL 的 ORM npm install --save sequelize
  • Pg 和 pg-hstore — pg 是 Node.js 的 PostgreSQL 客户端,pg-hstore 是一个用于将 JSON 数据序列化为 hstore 格式的 node 包 => npm install --save pg pg-hstore
  • Nodemon — 当文件更改时自动重启 Node 应用程序 => npm install nodemon –save-dev
  • Bcrypt — 用于密码哈希 => npm install bcrypt
  • Dotenv => 用于访问你的环境变量 => npm install dotenv
  • JSON Web Token => 用于生成令牌 => npm install jsonwebtoken
  • CookieParser => 用于设置 cookie => npm install cookie-parser

安装完成后,在 server.js 文件中添加以下内容,并修改你的 package.json 文件,添加一个启动脚本,如下所示:

// package.json
{"name": "backend","version": "1.0.0","description": "","main": "index.js","scripts": {"start": "nodemon server.js","test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC","dependencies": {"bcrypt": "^5.0.1","cookie-parser": "^1.4.6","dotenv": "^16.0.1","express": "^4.18.1","jsonwebtoken": "^8.5.1","pg": "^8.7.3","pg-hstore": "^2.3.4","sequelize": "^6.19.0"},"devDependencies": {"nodemon": "^2.0.16"}
}
第 2 步:数据库和服务器配置

在 server.js 文件中,导入你的模块,设置你的端口,并监听服务器连接。

// Server.js
// 导入模块
const express = require('express')
const sequelize = require('sequelize')
const dotenv = require('dotenv').config()
const cookieParser = require('cookie-parser')// 设置你的端口
const PORT = process.env.PORT || 8080// 将变量 app 分配给 express
const app = express()// 中间件
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(cookieParser())// 监听服务器连接
app.listen(PORT, () => console.log(`Server is connected on ${PORT}`))

接下来是使用 Model Views Controller (MVC) 方法创建你的文件夹结构:

  • 控制器
  • 模型
  • 路由
  • 中间件
  • 数据库配置

打开你的 pgAdmin 并创建你的数据库。

在 Models 文件夹中创建一个 index.js 文件,并使用 Sequelize ORM 设置你的数据库。

// Example for postgres database connection
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname')
// Model/index.js
// 导入模块
const { Sequelize, DataTypes } = require('sequelize')// 使用 postgres 方言指定数据库连接
// 我的数据库端口是 5433
// 数据库名称是 discover
const sequelize = new Sequelize('postgres://postgres:123456@localhost:5433/discover', { dialect: "postgres" })// 检查连接是否完成
sequelize.authenticate().then(() => {console.log('Database connected to discover')
}).catch((err) => {console.log(err)
})// 连接到模型
db.users = require('./userModel')(sequelize, DataTypes)// 导出模块
module.exports = db
第 3 步:设置你的用户模式

一旦你的数据库设置好了,在 Models 文件夹中创建另一个文件 userModel.js,使用 Sequelize 设置你的用户模式。

// user model
module.exports = (sequelize, DataTypes) => {const User = sequelize.define("user", {userName: {type: DataTypes.STRING,allowNull: false,},email: {type: DataTypes.STRING,unique: true,isEmail: true, // 检查电子邮件格式allowNull: false,},password: {type: DataTypes.STRING,allowNull: false,},}, { timestamps: true })return User
}
第 4 步:创建你的中间件

下一步是创建一个函数,该函数在将用户保存到数据库之前检查数据库中现有的用户名和电子邮件,以避免重复。在 middleware 文件夹中创建一个 userAuth.js 文件。

// 导入模块
const express = require("express");
const db = require("../Models");
// 将 db.users 分配给 User 变量
const User = db.users;// 函数用于检查数据库中是否已存在用户名或电子邮件
// 这是为了避免拥有相同用户名和电子邮件的两个用户
const saveUser = async (req, res, next) => {// 搜索数据库以查看用户是否存在try {const username = await User.findOne({where: {userName: req.body.userName,},});// 如果用户名在数据库中存在,则以 409 状态响应if (username) {return res.json(409).send("username already taken");}// 检查电子邮件是否已存在const emailcheck = await User.findOne({where: {email: req.body.email,},});// 如果电子邮件在数据库中存在,则以 409 状态响应if (emailcheck) {return res.json(409).send("Authentication failed");}next();} catch (error) {console.log(error);}
};// 导出模块
module.exports = {saveUser,
};
第 5 步:设置你的环境变量

.env 文件用于存储密钥。在你的根文件夹中创建一个 .env 文件,并在变量中保存随机字母。

例如:secretKey = ydwygyegyegcveyvcyegc

第 6 步:设置控制器

控制器包含将用户注册到我们的数据库和登录的逻辑。创建一个 userController.js 文件。控制器中有两个主要函数:

  • signup:在将密码保存到数据库之前,使用 bcrypt 对密码进行哈希
  • login:
    • 在数据库中查找请求的电子邮件,如果存在
    • 如果密码与数据库中的现有密码匹配,
    • 使用 (JWT) 生成带有用户 ID 的令牌,并使用 Cookie-Parser 为用户设置 cookie
    • 返回用户信息
// 导入模块
const bcrypt = require("bcrypt");
const db = require("../Models");
const jwt = require("jsonwebtoken");// 将 users 分配给变量 User
const User = db.users;// 用户注册
// 使用 bcrypt 在保存到数据库之前对用户密码进行哈希
const signup = async (req, res) => {try {const { userName, email, password } = req.body;const data = {userName,email,password: await bcrypt.hash(password, 10),};// 保存用户const user = await User.create(data);// 如果捕获到用户详细信息// 使用用户 ID 和 env 文件中的秘密密钥生成令牌// 设置带有生成令牌的 cookieif (user) {let token = jwt.sign({ id: user.id }, process.env.secretKey, {expiresIn: 1 * 24 * 60 * 60 * 1000,});} else {return res.status(409).send("Details are not correct");}} catch (error) {console.log(error);}
};// 登录认证const login = async (req, res) => {try {const { email, password } = req.body;// 通过电子邮件查找用户const user = await User.findOne({where: {email: email,},});// 如果找到用户电子邮件,使用 bcrypt 比较密码if (user) {const isSame = await bcrypt.compare(password, user.password);} else {return res.status(401).send("Authentication failed");}} catch (error) {console.log(error);}
};module.exports = {signup,login,
};
第 7 步:配置 Express 路由器

在 routes 文件夹中,通过使用 Express.js 提供的 Router 模块设置应用程序的路由。因此,在 routes 文件夹中创建一个名为 userRoutes.js 的文件。在 signup 路由中,传递中间件以检查数据库中用户名和电子邮件的重复项。

// 导入模块
const express = require("express");
const userController = require("../Controllers/userController");
const { signup, login } = userController;
const userAuth = require("../Middlewares/userAuth");const router = express.Router();// signup 端点
// 将中间件函数传递给 signup
router.post("/signup", userAuth.saveUser, signup);// login 路由
router.post("/login", login);module.exports = router;
第 8 步:重构服务器代码

在导入路由和数据库模块后,你的最终 server.js 应该看起来像这样:

// 导入模块
const express = require("express");
const sequelize = require("sequelize");
const dotenv = require("dotenv").config();
const cookieParser = require("cookie-parser");
const db = require("./Models");
const userRoutes = require("./Routes/userRoutes");// 设置你的端口
const PORT = process.env.PORT || 8080;// 将变量 app 分配给 express
const app = express();// 中间件
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());// 同步数据库并强制设置为 false,以防我们丢失数据
db.sequelize.sync({ force: true }).then(() => {console.log("db has been re sync");
});// 用户 API 的路由
app.use("/api/users", userRoutes);// 监听服务器连接
app.listen(PORT, () => console.log(`Server is connected on ${PORT}`));
第 9 步:测试

使用 Postman 或 REST 客户端测试你的端点。

打开终端并运行,npm start

注册 API
curl -X POST --data '{"userName": "aichaoxy","email": "aichaoxy@example.com","password": "password"
}' http://localhost:8080/api/users/signup
登录 API
curl -X POST --data '{"email": "aichaoxy@example.com","password": "password"
}' http://localhost:8080/api/users/login
结论

祝贺!你已成功使用 Sequelize(ORM)、PostgreSQL 和 Express 完成了用户认证。


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

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

相关文章

探索Baidu Comate:编程世界中的新利器

文章目录 Baidu Comate 介绍Baidu Comate的优势Baidu Comate安装过程Baidu Comate实战演练代码调优代码解释代码生成注释生成 总结 Baidu Comate 介绍 随着GPT的大火,衍生了各种AI工具,这些AI工具遍布在各行业各领域中,有AI写作、AI办公、AI…

向各位请教一个问题

这是菜鸟上的一道题目,单单拿出来问问大家,看看能不能解惑 ,谢谢各位! 题目25:求12!3!...20!的和 解题思路:这个题不知道为什么我用DEV C 5.11显示出来为0.000000,可能版本有问题?&a…

jenkins部署服务到windows系统服务器

1、安装openSSH windows默认不支持ssh协议,需要下载安装,主要适用于jenkins传输文件已经执行命令使用 点击查看下载openSSH 2、项目配置 这里简单说说怎么配置,主要解决点就是ssh执行cmd或shell命令时不能开启新窗口导致应用部署失败或者断…

【论文阅读笔记】MAS-SAM: Segment Any Marine Animal with Aggregated Features

1.论文介绍 MAS-SAM: Segment Any Marine Animal with Aggregated Features MAS-SAM:利用聚合特征分割任何海洋动物 Paper Code(空的) 2.摘要 最近,分割任何模型(SAM)在生成高质量的对象掩模和实现零拍摄图像分割方面表现出卓越…

海云安受邀参加诸子云 4.27南京「金融互联网」私董会

4月27日,“安在新媒体网安用户行业活动”第四期私董会在南京顺利举办。活动以“金融&互联网”为主题,邀请十余位业内资深的甲方用户以及典型厂商代表。摒弃传统的议题分享,采取“随时问答,自由讨论”的形式,提问题…

Poisson_Image-Editing

1.算法介绍 快速泊松图像编辑(Fast Poisson Image Editing)是一种图像处理算法,用于将源图像的某个区域无缝地嵌入到目标图像中。它基于泊松方程的性质,通过求解离散化的泊松方程来实现图像的融合。该算法的核心思想是&#xff0c…

信息系统项目管理师0092:项目管理原则(6项目管理概论—6.4价值驱动的项目管理知识体系—6.4.1项目管理原则)

点击查看专栏目录 文章目录 6.4价值驱动的项目管理知识体系6.4.1项目管理原则1.原则一:勤勉、尊重和关心他人2.原则二:营造协作的项目管理团队环境3.原则三:促进干系人有效参与4.原则四:聚焦于价值5.原则五:识别、评估和响应系统交互6.原则六:展现领导力行为7.原则七:根…

在家中访问一个网站的思考

在家中访问一个网站的思考 1、家庭网络简介2、家庭WLAN DHCP2.1、家庭路由器PPPOE拨号2.2、DHCP(动态主机配置协议)2.3、接入家庭网的主机IP地址2.4、家庭总线型以太网2.5、Mac地址2.6、ARP协议2.7、IP协议 & UDP/TCP协议2.8、NAT(Netwo…

沙盘Sandboxie v5.56.4

菜鸟高手裸奔工具沙盘Sandboxie是一款国外著名的系统安全工具,它可以让选定程序在安全的隔离环境下运行, 只要在此环境中运行的软件,浏览器或注册表信息等都可以完整的进行清空,不留一点痕迹。同时可以防御些 带有木马或者病毒的…

OpenHarmony usb打开报错“usb fail error code = -3, error msg = LIBUSB_ERROR_ACCESS”

一、前言:最近公司项目需求,定位要求使用国产系统,国产系统无非就是 统信os ,麒麟OS, 还有这两年比较热的 OpenHarmony。于是,老板要求公司产品适配OpenHarmony , 跟上时代步伐。 二、在开发中使用 usb 通讯时&#x…

Unity射击游戏开发教程:(12)使用后处理

后处理 后期处理是向您的游戏场景添加一个或多个滤镜,确实可以为您的游戏提供精美的外观。在本文中,我们将讨论如何在 Unity 中设置后处理系统,从那里您可以探索和试验 Unity 提供的所有过滤器。 首先,我们需要从包管理器添加后处理器堆栈。包管理器是 Unity 产品的集合,…

淘宝数据分析——Python爬虫模式♥

大数据时代, 数据收集不仅是科学研究的基石, 更是企业决策的关键。 然而,如何高效地收集数据 成了摆在我们面前的一项重要任务。 本文将为你揭示, 一系列实时数据采集方法, 助你在信息洪流中, 找到…

怎么在家访问公司内网?

在当前的疫情情况下,越来越多的公司开始允许员工在家办公,这就需要解决一个问题:如何在家访问公司的内网资源呢?今天我将介绍一种解决方案——使用【天联】组网,它具有许多优势。 【天联】组网的优势 无网络限制&#…

在Node.js(express 框架)中使用 JWT 进行身份认证

文章目录 一、JWT 认证机制二、安装 JWT 相关的包三、基本使用1、生成 JWT 字符串2、添加中间件,解析 JWT 字符串3、获取管理员信息(admin) 一、JWT 认证机制 JWT 认证机制(图片来源于网络,侵权删除): 关于 JWT 原理可…

Conda下Richdem包遇到问题

Conda中Richdem包遇到问题 文章目录 Conda中Richdem包遇到问题问题一报错解决 问题二报错解决 参考 问题一 报错 RichDEM 是一套数字高程模型 (DEM) 水文分析工具,这次打算用richdem进行地形分析,尝试在conda里面安装richdem包的…

HDLC协议

目录 1.概念 2.配置 3.HDLC帧结构 4.HDLC帧类型 1.概念 HDLC(High-level Data Link Control)高级数据链路控制位于链路层协议,传输单位是帧,它是一组用于在网络结点间传送数据的协议。其特点是各项数据和控制信息都以比特为单位&#xff…

CUDA-共享内存法实现矩阵乘法(比常规方案提速一倍)

作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 共享内存是什么? 共享内存是在多个处理单元之间共享数据的一种内存区域。在计算机体系结构中,共享内存通…

S型曲线的几种设计(图像对比度调节)

一般来讲,图像调色模块都会提供“曲线”工具,这是一个极其灵活的功能,绝大部分的调色都可以通过该工具实现,但是曲线功能的交互相对而言比较复杂。出于简便性和效率方面的考量,调色模块往往还会提供一些具有很强的功能…

最后一块石头的重量 II ,目标和,一和0

最后一块石头的重量 II(0-1背包问题 将石头尽可能分为两堆重量一样的,进行相撞则为0 class Solution {public int lastStoneWeightII(int[] stones) {int sum0;for(int x:stones){sumx;}int targetsum/2;int[] dpnew int[target1];//dp[j]表示最大石堆的…

AI视频教程下载:学会用AI创作文本图片音频视频

在不断发展的科技领域,人工智能 (AI) 是毋庸置疑的冠军,它是一种不断创新的力量,在我们的生活中扮演着越来越重要的角色。随着 2023 年的到来,我们诚挚地欢迎您加入人工智能精通课程的大门。 这不仅仅是一个课程,它专为…