Express 验证

摘要: 在本教程中,您将学习如何使用 express-validator 库来验证和清理输入数据。

当您的 Express 应用程序从外部来源(如用户输入)接收数据时,对输入数据进行验证清理至关重要。

  • 数据验证确保输入数据满足某些条件,例如类型、范围和格式。它验证输入数据是否有效。例如,您可以检查电子邮件地址是否具有有效的格式。
  • 数据清理通过删除或转义有害字符来清理输入数据。它有助于防止恶意输入,例如代码注入。例如,您可以在将输入数据渲染到网页之前,从输入数据中删除 HTML 或脚本标记。

在 Express 应用程序中,您可以手动验证和清理输入数据,但此过程很耗时,需要更多努力。

为了提高效率,您可以使用第三方验证库。在本教程中,您将学习如何使用 express-validator 库 来验证和清理输入数据。

验证查询字符串

首先,创建一个简单的 Express 应用程序

import express from 'express';

const PORT = process.env.PORT || 3000;
const app = express();

app.get('/hi', (req, res) => res.send(`Hi, ${req.params.name}!`));

app.listen(PORT, () => console.log(`The server is listening on port ${PORT}`));Code language: JavaScript (javascript)

该应用程序包含一个路由/hi,它接受一个查询字符串name。它将在 Web 浏览器上显示问候消息。

其次,通过在终端中运行以下npm命令,在项目中安装express-validator

npm install express-validatorCode language: JavaScript (javascript)

第三,创建一个对以下端点的请求

http://localhost:3000/hi?name=JohnCode language: JavaScript (javascript)

它将在 Web 浏览器上显示以下消息

Hi, John!Code language: JavaScript (javascript)

但是,如果您在不传递name查询字符串的情况下请求以下端点

http://localhost:3000/hiCode language: JavaScript (javascript)

您将在屏幕上看到以下消息

Hi, undefinedCode language: JavaScript (javascript)

原因是在此示例中,req.query.nameundefined

在最坏的情况下,如果查询字符串包含 JavaScript 代码,您可能会被重定向到恶意页面。例如

http://localhost:3000/hi?name=<script>window.location ='https://www.google.com';</script>Code language: JavaScript (javascript)

在此示例中,我们注入将重定向到 google.com 的代码。在实际场景中,您可能会被重定向到恶意页面。这称为跨站点脚本 (XSS)。

跨站点脚本 (XSS) 是一种攻击,攻击者在受信任网站的代码中注入恶意可执行脚本。

要验证和清理name查询字符串的值,可以使用express-validator库。

从技术上讲,express-validator库是一组中间件函数,用于验证和清理输入数据。

第四,使用express-validator库中的函数验证name查询字符串

import express from 'express';
import { query, validationResult, matchedData } from 'express-validator';

const PORT = process.env.PORT || 3000;
const app = express();

app.get('/hi', query('name').notEmpty().escape(), (req, res) => {
  // validate data
  const result = validationResult(req);
  if (!result.isEmpty()) {
    res.status(400).send({ errors: result.array() });
  }

  // sanitize data
  const cleanedData = matchedData(req);
  res.send(`Hi, ${cleanedData.name}!`);
});

app.listen(PORT, () => console.log(`The server is listening on port ${PORT}`));Code language: JavaScript (javascript)

工作原理。

步骤 1. 从express-validator库导入函数以处理验证

import { query, validationResult, matchedData } from 'express-validator';Code language: JavaScript (javascript)

以下是导入函数的摘要

  • query()函数是验证查询参数的中间件。
  • validationResult()函数收集对传入请求的验证和清理结果。
  • matchedData()函数提取验证和清理后的数据。

步骤 2. 验证 name 查询字符串

query('name').notEmpty().escape()Code language: JavaScript (javascript)

在此语法中

  • notEmpty()函数确保 name 查询字符串的值不为空。
  • escape()函数转义字段值以防止 XSS 攻击。

query()notEmpty()escape()函数形成一个验证链。由于它们返回一个中间件函数,因此我们可以在app.get()方法中使用它。

步骤 3. 使用validationResult()函数获取验证结果

const result = validationResult(req);
if (!result.isEmpty()) {
   res.status(400).send({ errors: result.array() });
}Code language: JavaScript (javascript)

query()函数不会自动报告验证错误。相反,它收集验证错误,然后使用validationResult()函数进行验证。validationResult()函数返回一个ValidationError对象。

ValidationError对象的isEmpty()方法在没有发生验证错误时返回true,否则返回false。在代码中,我们返回一个包含验证错误的 JSON 响应,并使用 HTTP 状态码 400。

步骤 4. 获取清理后的数据

要获取清理后的数据,可以使用matchedData()函数

const cleanedData = matchedData(req);Code language: JavaScript (javascript)

步骤 5. 渲染清理后的数据

res.send(`Hi, ${cleanedData.name}!`);Code language: JavaScript (javascript)

验证路由参数

要验证路由参数,可以使用express-validator库中的param()函数。

param()函数允许您为路由参数指定验证规则。

以下示例显示了如何使用param()函数验证 id 路由参数

app.get(
  '/api/todos/:id',
  param('id').isInt({ min: 1 }).withMessage('ID must be a positive integer'),
  (req, res) => {
    const errors = validationResult(req);

    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    const id = req.params.id;
    res.send(`Fetching record with ID: ${id}`);
  }
);Code language: JavaScript (javascript)

工作原理。

param('id')指定用于验证的id路由参数

  • isInt({ min: 1 })确保id参数为整数,且至少为 1。
  • withMessage('ID 必须是正整数')指定在验证失败时的自定义错误消息。

其余代码的工作方式与验证查询字符串相同。

验证请求主体

步骤 1. 要将请求处理为 JSON 对象,请注册名为express.json()的内置中间件

app.use(express.json());Code language: JavaScript (javascript)

这指示 Express 应用程序将主体解析为 JSON 对象,允许您通过req.body属性访问它。

要访问 JSON 对象的字段,可以使用express-validator库中的body()函数。

步骤 2. 从express-validator库导入body函数

import {body, validationResult, matchedData} from 'express-validator';Code language: JavaScript (javascript)

步骤 3. 验证请求主体中的titlecompleted字段

app.post('/api/todos',
  [body('title').notEmpty().isString(), body('completed').isBoolean()],
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).send({ errors: errors.array() });
    }

    const record = matchedData(req);
    res.send(record);
  }
);Code language: JavaScript (javascript)

在此示例中,我们将中间件数组传递给app.post()函数。第一个中间件验证title字段,第二个中间件验证请求主体中的completed字段。

例如,如果您向/api/todos端点发出 POST 请求,但在请求主体中没有指定titlecompleted字段,您将收到以下错误

{
  "errors": [
    {
      "type": "field",
      "msg": "Invalid value",
      "path": "title",
      "location": "body"
    },
    {
      "type": "field",
      "msg": "Invalid value",
      "path": "title",
      "location": "body"
    },
    {
      "type": "field",
      "msg": "Invalid value",
      "path": "completed",
      "location": "body"
    }
  ]
}Code language: JavaScript (javascript)

总结

  • 使用query()函数验证查询字符串。
  • 使用param()函数验证路由参数。
  • 使用body()函数验证请求主体。
本教程是否有帮助?