如何通过 3 个步骤使用 JWT Auth 和 PostgreSQL 初始化多层 Node.js RESTful API GenAI LIVE!| 2025 年 6 月 4 日

2025-06-10

如何通过 3 个步骤使用 JWT Auth 和 PostgreSQL 初始化多层 Node.js RESTful API

GenAI LIVE! | 2025年6月4日

鲜为人知的是,尤利乌斯·凯撒的名言“分而治之”实际上指的是使用分层架构构建Web应用程序。其原理在于将用户界面与业务逻辑分离,将业务逻辑与数据访问逻辑分离。分层架构提供了更高的灵活性、可维护性和可扩展性,并且更易于编写、测试和维护。听起来不错,但如何使用现代技术来实现它呢?

对于那些刚接触 Node.js 和 RESTful API 的新手,我们编写了一份指南,旨在帮助您创建一个可以发展成大型服务的 RESTful API。在本教程中,我们将分三步向您展示如何构建 RESTful API。JSON Web Token 技术将帮助我们处理身份验证,并使用 PostgreSQL 作为数据库。

因此,我们编写 RESTful API 的步骤是:

  1. 初始化 Node.js 项目
  2. JWT 身份验证
  3. 添加图层

初始化 Node.js 项目

让我们开始构建我们的应用程序。创建一个空文件夹,并使用以下命令初始化一个新项目:npm init

要安装必要的软件包,请运行以下命令:npm i bcrypt bluebird body-parser express http jsonwebtoken lodash pg sequelize sequelize-values — save

接下来,在主文件夹中创建以下文件:

  • config.js(应用程序的配置,如数据库连接、密码盐等)
  • db.js(负责数据库连接)
  • router.js(处理 http 请求并将其分派给控制器)
  • index.js  —(启动文件)

以下是我们的文件包含的代码:

配置.js:

module.exports = { 
port: 3000,
dbConnectionString: '你的 postgresql 连接',
saltRounds: 2,
jwtSecret: 'yo-its-a-secret',
tokenExpireTime: '6h'
}

db.js:

const config = require('./config');
const Sequelize = require('sequelize');
var sequelize = new Sequelize(config.dbConnectionString);
require('sequelize-values')(sequelize);
module.exports = sequelize;

router.js:

module.exports.set = app => {
//endpoints will be here soon
}

index.js:

const express = require('express');
const http = require('http');
const bodyParser = require('body-parser');
const app = express();
const config = require('./config');
const router = require('./router');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static('client'));
router.set(app);
app.listen(config.port, () => console.log('App listening on port '+ config.port));

在主文件夹中创建完文件后,你需要定义数据模型。为此,创建一个 models 文件夹,其中包含index.js文件。如下所示:

/models/index.js:

const Sequelize = require('sequelize');
const sequelize = require('../db');
const User = sequelize.define('user', {
login: Sequelize.STRING,
password: Sequelize.STRING,
});
const Order = sequelize.define('order', {
title: Sequelize.STRING,
date: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW
},
user_id: {
type: Sequelize.INTEGER,
references: {
model: User,
key: 'id'
}
}
});
User.hasMany(Order, {foreignKey: 'user_id'});
module.exports = {
User,
Order
}

这就是你启动多层 Node.js 项目的方式。目前,我们有一个应用程序的入口点 ( index.js )、两个数据库模型 ( models/index.js ) 以及一些基本配置。

JWT 身份验证

在编写实际 API 之前,让我们先为应用程序添加身份验证。创建一个 services 文件夹,其中包含文件user.jsauth.js。如下所示:

/services/index.js

const sequelize = require('../db');
const Users = require('../models').User;
const addUser = user => Users.create(user);
const getUserByLogin = login => Users.findOne({where: {login}});
module.exports = {
addUser,
getUserByLogin
}

用户登录后,后续每个请求都会包含一个令牌(JWT),用户可以根据令牌中存储的权限访问路由、服务和资源。

/services/auth.js 将处理 JWT 身份验证:

const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const Users = require('../models').User;
const config = require('../config');
const authenticate = params => {
return Users.findOne({
where: {
login: params.login
},
raw: true
}).then(user => {
if (!user)
throw new Error('Authentication failed. User not found.');
if (!bcrypt.compareSync(params.password || '', user.password))
throw new Error('Authentication failed. Wrong password.');
const payload = {
login: user.login,
id: user.id,
time: new Date()
};
          var token = jwt.sign(payload, config.jwtSecret, {
expiresIn: config.tokenExpireTime
});
return token;
});
}

module.exports = {
authenticate
}

为了处理注册和身份验证请求,我们的应用程序应该有一个控制器。

让我们创建一个文件auth.js并将其放在 controllers 文件夹中。

/控制器/auth.js:

const config =  require('../config');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const authService = require('../services/auth');
const userService = require('../services/user');
function login(req, res){
return authService.authenticate(req.body)
.then(token => {
res.send({
success: true,
data: { token }
});
})
.catch(err => {
res.send({
success: false,
message: err.message //not the best error handling.
//for better error handling visit github repository, link provided below
});
})
};
function register(req, res){
var login = req.body.login;
return userService.getUserByLogin(req.body.login || '')
.then(exists => {
          if (exists){
return res.send({
success: false,
message: 'Registration failed. User with this email already registered.'
});
}
          var user = {
login: req.body.login,
password: bcrypt.hashSync(req.body.password, config.saltRounds)
}
          return userService.addUser(user)
.then(() => res.send({success: true}));
});
};
module.exports = {
login,
register
}

在此之后,我们需要向我们的 API 添加端点。

您可以在 router.js 文件中执行此操作:

const authController = require('./controllers/auth');
module.exports.set = app => {
app.post('/login', authController.login);
app.post('/register', authController.register);
}

让我们通过运行命令 node index.js启动服务器并测试登录和注册功能。

添加图层

现在我们的应用程序中已经有了控制器层和数据访问层。为了将它们连接在一起,我们需要在它们之间添加服务层。使用层是确保职责分离的好方法,这使得数据、业务逻辑和表示代码能够相互独立。表示层(用户)与控制器层(API)交互,控制器层使用服务层(业务规则)通过数据访问层访问和修改数据。

那么,让我们从订单模型的第一个服务开始。

创建文件 services/order.js

const Orders = require('../models').Order;
const getAll = () => Orders.findAll();
const getById = id => Orders.findById(id);
const add = order => Orders.create(order);
module.exports = {add, getAll, getById};

现在,我们可以创建一个控制器来与该服务协同工作。

控制器/order.js

const orderService = require('../services/order');
function getOrders(req, res){
orderService.getAll()
.then(data => res.send(data));
};
function getOrder(req, res){
orderService.getById(req.params.id)
.then(data => res.send(data));
}
function addOrder(req, res){
orderService.add({
title: req.body.title,
user_id: 1
})
.then(data => res.send(data));
};
module.exports = {
getOrders,
getOrder,
addOrder
}

我们还需要做一件事来完成 RESTful API 的订单部分,那就是将端点添加到 router.js:

const orderController = require('./controllers/order');

app.get('/orders', orderController.getOrders);
app.get('/orders/:id', orderController.getOrder);
app.post('/orders', orderController.addOrder);

以下是一些有效 API 的测试说明:

接下来我们需要做的是只允许经过身份验证的用户访问。为此,让我们添加检查用户是否已登录的中间件:

中间件/auth.js:

const jwt = require('jsonwebtoken');
const config = require('../config');
const checkAuth = (req, res, next) => {
var token = req.headers['token'];
if (!token)
return res.status(403).send({ auth: false, message: 'No token provided.' });

jwt.verify(token, config.jwtSecret, (err, decoded) => {
if (err)
return res.status(500).send({ auth: false, message: 'Failed to authenticate token.' });
    req.user = {
login: decoded.login,
id: decoded.id
};
    next();
});
}
module.exports = {
checkAuth
}

此后,身份验证中间件应作为端点函数中的中间件参数(第二个参数)使用。现在,用户如果不提供有效的身份验证令牌,就无法访​​问数据。

app.get('/orders', authMiddleware.checkAuth, orderController.getOrders);
app.get('/orders/:id', authMiddleware.checkAuth, orderController.getOrder);
app.post('/orders', authMiddleware.checkAuth, orderController.addOrder);
app.get('/user_orders', authMiddleware.checkAuth, userController.getUsersWithOrders)

正如你所见,它起作用了:)

我们需要做的最后一件事是定义 addOrder 函数。

function addOrder(req, res){
orderService.add({
title: req.body.title,
user_id: req.user.id
})
.then(data => res.send(data));
};

就这样!我们创建了一个使用 RESTful API 的小型应用。根据多层架构的概念,我们定义了控制器层、服务层和数据访问层。我们的 API 支持 JWT 授权,可以轻松添加展示层,例如 Web 应用或移动应用。

欢迎随时查看代码库中的代码。别傻傻地站在那里,赶紧尝试一下吧。ElifTech 祝好运!

链接:https://dev.to/vitaliikulyk/how-to-initialize-multilayer-nodejs-restful-api-with-jwt-auth-and-postgresql-in-3-steps--c8c
PREV
Python Zero to Hero #初学者⚡ 先决条件:1. 你的机器中已经安装了 Python。如果你已经在系统中安装了 Python,请按 Win 键并打开命令提示符 Python 中的 Hello World 注释 Python 中的数据类型从用户那里获取输入并将其存储在变量中 列表和索引 Python 运算符 Python 字符串操作 Python 中的集合 Python 中的类型转换 Python 中的子集 列表操作 字符串操作 缩进 使用函数 Python 中的 For 循环 If 语句:If 语句,没有缩进(将引发错误) Python 中的 While 循环 异常处理 使用模块现在怎么样?列表在 Python 中是可变的
NEXT
如何在工作中成长并受到关注