摘要: 在本教程中,您将学习如何使用 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://:3000/hi?name=JohnCode language: JavaScript (javascript)它将在 Web 浏览器上显示以下消息
Hi, John!Code language: JavaScript (javascript)但是,如果您在不传递name查询字符串的情况下请求以下端点
http://:3000/hiCode language: JavaScript (javascript)您将在屏幕上看到以下消息
Hi, undefinedCode language: JavaScript (javascript)原因是在此示例中,req.query.name为undefined。
在最坏的情况下,如果查询字符串包含 JavaScript 代码,您可能会被重定向到恶意页面。例如
http://: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. 验证请求主体中的title和completed字段
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 请求,但在请求主体中没有指定title和completed字段,您将收到以下错误
{
"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()函数验证请求主体。