Article Cover Image - Securing APIs: Express rate limit and slow down
赞助

保护 API:Express 速率限制和减速

阅读时间 6 分钟

速率限制和慢速机制有助于维持 Web 应用程序的稳定性、安全性和性能。这些控制可以防止系统过载,并提供一定程度的保护,抵御暴力破解和分布式拒绝服务 (DDoS) 攻击。速率限制还可以提高应用程序的可伸缩性,并通过维持服务质量和可靠性来增强用户体验。

内容分发网络 (CDN) 和网络级解决方案是保护项目免受这些问题影响的流行且便捷的方式,但您也可以直接在应用程序中实施控制和慢速逻辑。这种方法让您可以更好地控制服务器的行为,并在 CDN 或 DDoS 防护出现故障时提供额外的后备方案。此外,非恶意的脚本或应用程序集成也可能由于 bug 或网络问题而出现故障。速率限制和慢速机制可以阻止程序过度执行操作,无意中消耗系统或网络资源。

在本文中,我们将创建一个 Express 应用程序,并集成速率限制和慢速逻辑,使其更具可伸缩性和安全性。保护应用程序的安全有许多方面,但通过使用本文介绍的方法,您应该能够轻松地配置一种额外的方式来确保您的 Express 应用程序更具弹性和安全性。

在 Vultr 上设置 Express 应用

首先,按照我们上一篇文章中在 Vultr 上部署服务器部分中的步骤部署服务器。接下来,让我们通过 SSH 访问服务器终端,并为我们的 Web 应用程序设置一个项目。

我们将使用 Nano 文本编辑器在服务器上创建和编辑项目文件。您可以查阅 快捷键备忘单以获取使用 Nano 的帮助。我们还将使用 Uncomplicated Firewall (UFW) 来控制允许进出服务器的流量。我们的 Express 应用使用端口 3000,因此我们可以通过 UFW 只允许通过此端口的入站流量。

  1. 创建一个项目目录,并进入该目录。

    bash
    mkdir express-api-security
    cd express-api-security
    
  2. 初始化一个 Node.js 项目。

    bash
    npm init -y
    
  3. 安装 Express 依赖项。

    bash
    npm install express
    
  4. 为着陆页创建一个新目录,并进入该目录。

    bash
    mkdir public
    cd public
    
  5. 创建一个 HTML 文件。

    bash
    nano index.html
    
  6. 将以下代码复制并粘贴到 index.html 文件中。

    html
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Express Rate Limit & Slow Down</title>
        <style>
          body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f0f0f0;
          }
          .container {
            text-align: center;
          }
          h1 {
            color: #333;
          }
          p {
            color: #666;
          }
        </style>
      </head>
      <body>
        <div class="container">
          <h1>Express Rate Limit & Slow Down Applied</h1>
          <p>Rate limiting and speed limiting are applied to this page.</p>
        </div>
      </body>
    </html>
    
  7. 保存并退出文件。

  8. 退出 public 目录,并创建一个 JavaScript 文件。

    bash
    cd ..
    nano app.js
    
  9. 将以下代码复制并粘贴到 app.js 文件中。

    js
    const express = require("express");
    const app = express();
    const port = 3000;
    
    app.use(express.static("public"));
    
    app.get("/", (req, res) => {
      res.sendFile(__dirname + "/public/index.html");
    });
    
    app.listen(port, () => {
      console.log(`Server is running on port ${port}`);
    });
    
  10. 允许入站连接到端口 3000

    bash
    ufw allow 3000
    
  11. 重新加载防火墙。

    bash
    ufw reload
    
  12. 运行 Node.js 应用程序。

    bash
    node app.js
    

如果您的应用程序正在运行,您应该会在控制台中看到“Server is running on port 3000”的日志,并且您可以通过服务器 IP 和端口 3000 访问该应用程序。

http://<server-ip>:3000

您可以根据需要多次重新加载网页,重新加载速度不受影响,因为没有应用速率限制和慢速机制。您可以通过按 Ctrl + C 来停止应用程序。

理解 Express 速率限制中间件

express-rate-limit 中间件用于控制对 Express 应用程序的入站请求速率。

  • windowMs:定义速率限制适用的时间(以毫秒为单位)。例如,windowMs: 15 * 60 * 1000 设置了一个 15 分钟的时间窗口。
  • max:指定在时间窗口内允许来自单个 IP 地址的最大请求数。如果请求超过此定义的限制,则会触发速率限制。

在 Express 应用程序中实现速率限制

在本节中,我们将把 express-rate-limit 中间件应用到 Express 应用程序。

  1. 安装 express-rate-limit 依赖项。

    bash
    npm install express-rate-limit
    
  2. 打开 express-api-security 目录中的 app.js 文件。

    bash
    nano app.js
    
  3. 添加中间件。您的 JavaScript 文件应如下所示:

    js
    const express = require("express");
    const rateLimit = require("express-rate-limit");
    
    const app = express();
    const port = 3000;
    
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000,
      max: 5,
    });
    
    app.use(limiter);
    app.use(express.static("public"));
    
    app.get("/", (req, res) => {
      res.sendFile(__dirname + "/public/index.html");
    });
    
    app.listen(port, () => {
      console.log(`Server is running on port ${port}`);
    });
    
  4. 保存并退出文件。

  5. 使用 node app.js 运行应用程序。

让我们看看我们在 app.js 中所做的更改。我们导入 express-rate-limit,并创建一个名为 limiter 的常量速率限制器,将其配置为在 15 分钟窗口内每个 IP 地址最多允许 5 个请求。

如果客户端超过定义的限制,后续请求将收到 429 (Too Many Requests) 状态码,直到时间窗口重置。您可以使用 app.use(limiter) 来启用中间件。

当您访问应用程序 URL 时,请多次刷新页面。当您刷新页面 6 次时,您将看到一个浏览器错误屏幕,显示“Too many requests, please try again later”。完成速率限制测试后,按 Ctrl + C 停止应用程序。

理解 Express 慢速中间件

express-slow-down 中间件会在响应请求时引入延迟。这种延迟有助于将入站请求分散到一段时间内,从而减少服务器负载。与速率限制不同,它不会在超出限制时立即拒绝请求。

  • delayAfter:指定在此之后开始应用减速效果的请求数。例如,将 delayAfter: 1 设置为表示在第一个请求后应用减速。
  • delayMs:指定在超出 delayAfter 定义的限制后添加到每个请求的延迟(以毫秒为单位)。

将慢速机制集成到 Express 应用程序中

在本节中,我们将把 Express 慢速中间件应用到 Express 应用程序。

  1. 安装 express-slow-down 依赖项。

    bash
    npm install express-slow-down
    
  2. 打开 express-api-security 目录中的 app.js 文件。

    bash
    nano app.js
    
  3. 添加中间件。您的 JavaScript 文件应如下所示:

    js
    const express = require("express");
    const rateLimit = require("express-rate-limit");
    const slowDown = require("express-slow-down");
    
    const app = express();
    const port = 3000;
    
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000,
      max: 5,
    });
    
    const speedLimiter = slowDown({
      windowMs: 15 * 60 * 1000,
      delayAfter: 1,
      delayMs: () => 2000,
    });
    
    app.use(speedLimiter);
    app.use(limiter);
    app.use(express.static("public"));
    
    app.get("/", (req, res) => {
      res.sendFile(__dirname + "/public/index.html");
    });
    
    app.listen(port, () => {
      console.log(`Server is running on port ${port}`);
    });
    
  4. 保存并退出文件。

  5. 使用 node app.js 运行应用程序。

我们对 app.js 所做的更改与之前对速率限制所做的更改类似。我们导入 express-slow-down,并创建一个名为 speedLimiter 的常量速度限制中间件。我们添加的配置会在 1 个请求后减慢请求速率,在 15 分钟窗口内为每个后续请求添加 2000 毫秒(2 秒)的延迟。同样,您可以使用 app.use(speedLimiter) 来启用中间件。

当您访问应用程序 URL 时,尝试反复刷新页面。您会看到每次刷新时页面加载所需的时间都会增加。这是为了说明目的而过度使用减速,因此您可以在实际应用程序中为更多的请求启用速度限制。好处是,这可以根据您的应用程序的实际使用情况进行配置。

实际用途和示例

让我们看看速率限制和慢速在实际应用程序中的应用。以下是两个常见用例:

  • 社交媒体平台提供允许开发人员访问其数据的 API。但是,为了防止滥用并确保公平使用,这些平台集成了速率限制。

    • API 端点定义了速率限制,规定了在特定时间范围内每个用户可以发出的请求数量。
    • 它们还集成了慢速机制,以防止突然的请求爆发。
  • 电子商务网站在节假日期间会经历流量高峰。为了防止服务器过载,确保流畅的结账流程,并防范欺诈,这些平台在结账和订单处理工作流程中集成了速率限制和慢速机制。

    • 结账和订单处理端点会限制请求数量,例如在特定时间范围内将商品添加到购物车或提交订单。
    • 在超出初始速率限制后,额外的请求可能会被延迟,从而确保服务器能够在不被突然的流量浪涌压垮的情况下处理入站订单。

总结

在本文中,我们创建了一个 Express 应用,并学习了如何包含速率限制和慢速机制。通过学习如何在项目中集成和配置这些功能,您将能够创建可伸缩的服务器端 Node.js 应用,这些应用具有更健壮的请求处理能力,以提高安全性和弹性。

这是一篇由 Vultr 赞助的文章。Vultr 是全球最大的私营云计算平台。Vultr 是开发者的首选,已为 185 个国家/地区的 150 万多客户提供了灵活、可扩展、全球化的云计算、云 GPU、裸金属和云存储解决方案。了解更多关于 Vultr 的信息。