【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,一经查实,立即删除!

相关文章

Linux上安装及卸载OpenJDK

Linux上安装Java Development Kit (JDK) 8的步骤如下: 1. 添加Java JDK 8的Yum源 首先,你需要添加Java JDK 8的Yum源到系统。这可以通过下载并安装Oracle JDK的方式完成,但由于Oracle JDK在某些情况下可能需要遵守特定的许可协议&#xff0c…

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

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

[力扣题解] 216. 组合总和 III

题目&#xff1a;216. 组合总和 III 思路 回溯法 代码 class Solution { private:vector<vector<int>> result;vector<int> path;public:void function(int k, int n, int startindex, int sum){int i;// 剪枝// 超过了, 不用找了;if(sum > n){return…

向各位请教一个问题

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

linux挂载数据盘详细步骤

在 Linux 上挂载数据盘通常涉及以下步骤&#xff1a; 1. **识别数据盘**&#xff1a;首先&#xff0c;你需要找到要挂载的磁盘设备。在命令行中使用 lsblk 或 fdisk -l 命令查看系统中的磁盘和分区。你会看到类似 sda, sdb, sdc 这样的设备名称&#xff0c;以及各自的分区。 l…

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

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

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

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

阿里/腾讯/华为云国际使用须知

一&#xff1a;针对国内客户业务&#xff1a;务必限制国内IP的访问。建议客户使用代理进行访问&#xff0c;或者考虑使用第三方CDN服务来屏蔽腾讯云国际服务器的IP或域名&#xff0c;以降低客户投诉和风控服务器风险。 二&#xff1a;对于国外客户业务&#xff1a;务必设置禁止…

【spark实战:报错】spark序列化报错:Kryo serialization failed: Buffer overflow

文章目录 spark序列化报错问题解决 spark序列化报错 org.apache.spark.SparkException: Kryo serialization failed: Buffer overflow. Available: 0, required: 61186304. To avoid this, increase spark.kryoserializer.buffer.max value.at org.apache.spark.serializer.Kry…

第 7 章 MyBatis 缓存配置

第 7 章 MyBatis 缓存配置 一. 一级缓存1. 代码讲解一级缓存2. 关闭一级缓存的方法二. 二级缓存1. 介绍2. 配置二级缓存2.1 开启二级缓存全局配置2.2 两种配置方法2.3 mapper.xml中配置二级缓存 ❤❤❤默认配置配置参数讲解2.4 Mapper 接口中配置二级缓存❤❤❤2.5 同时使用时注…

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

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

Poisson_Image-Editing

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

Shell 初始化配置指北 | Ubuntu

唠唠闲话 概要&#xff1a;在不同的Shell环境&#xff08;如Bash和Zsh&#xff09;中设置环境变量、设置初始脚本&#xff0c;以及如何根据不同的使用场景&#xff08;用户级或系统级&#xff09;管理和设置初始运行命令。 p.s. 如果你很熟悉 Linux&#xff0c;推荐跳到最后一…

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

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

如何使用Knife4j进行接口测试

Knife4j是一个为Java MVC框架提供增强的Swagger UI界面的开源工具&#xff0c;它集成了Swagger UI并提供了更丰富的功能。使用Knife4j可以进行接口的测试&#xff0c;以下是使用Knife4j进行接口测试的详细步骤和解释&#xff1a; 1. 引入Knife4j依赖 首先&#xff0c;确保你的…

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

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

srpingboot 根据配置文件判断是否加载某个javaConfig配置

1. 场景 项目通过配置文件值动态判断配置为kafka或rabbitmq的消息队列作为中间件。 2.实现 通过实现Condition接口&#xff0c;重写matches方法来进行场景判断&#xff1a; 2.1. kafka的Confition开关&#xff1a; package com.hero.kafka.config;import org.springframew…

沙盘Sandboxie v5.56.4

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

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

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

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

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