【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 步:测试
先决条件

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

第 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 文件中的秘密密钥生成令牌
    // 设置带有生成令牌的 cookie
    if (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 完成了用户认证。


  • 27
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Node.js是一个基于Chrome V8引擎的JavaScript运行时环境,它允许开发者使用JavaScript语言进行服务器端编程。Node.js具有高效、轻量级和事件驱动的特点,适用于构建高性能的网络应用程序。 在Node.js中,可以使用各种模块和框架来进行Web服务器开发。以下是一些常用的模块和框架: 1. HTTP模块:Node.js内置的HTTP模块提供了创建HTTP服务器和客户端的功能。通过该模块,可以监听HTTP请求、处理请求和发送响应。 2. Express框架:Express是一个流行的、灵活的Node.js Web应用程序框架。它提供了简化路由、中间件管理和模板引擎等功能,使得构建Web服务器变得更加容易。 3. Koa框架:Koa是一个新一代的Node.js Web框架,由Express团队开发。它使用了ES6的新特性,提供了更简洁、更强大的异步流程控制能力。 4. Socket.IO:Socket.IO是一个实时应用程序框架,可以在服务器和客户端之间建立双向通信。它基于WebSocket协议,并提供了跨浏览器的兼容性。 5. MongoDB:MongoDB是一个流行的NoSQL数据库,适用于存储和检索大量的非结构化数据。在Node.js中,可以使用Mongoose模块来连接和操作MongoDB数据库。 6. SequelizeSequelize是一个强大的ORM(Object-Relational Mapping)库,用于在Node.js中操作关系型数据库。它支持多种数据库,如MySQL、PostgreSQL和SQLite等。 以上只是一些常用的模块和框架,Node.js生态系统非常丰富,还有很多其他的模块和工具可供选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值