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

API 安全:Express 速率限制和延迟

作者头像Vultr阅读时长 7 分钟

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

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

在本文中,我们将创建一个 Express 应用程序,并结合速率限制和延迟逻辑,使其更具可扩展性和安全性。保护应用程序有很多方面,但通过使用本文中描述的方法,您应该能够轻松地配置另一种方法,确保您的 Express 应用程序更具弹性和安全性。

在 Vultr 上设置 Express 应用程序

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

我们将使用Nano 文本编辑器在服务器上创建和编辑项目文件。您可以查看快捷方式备忘单,了解使用 Nano 的帮助。我们还将使用简单防火墙 (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
    

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

http://<server-ip>:3000

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

了解 Express 速率限制中间件

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

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

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

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

  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 (太多请求) 状态代码,直到时间窗口重置。您可以使用app.use(limiter)启用中间件。

当您访问应用程序 URL 时,刷新页面几次。当您刷新页面 6 次时,您将看到一个浏览器错误屏幕,显示“太多请求,请稍后再试”。完成速率限制测试后,通过按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的信息。

关注 MDN 的最新资讯

订阅 MDN 新闻通讯,不错过任何关于最新 Web 开发趋势、技巧和最佳实践的更新。