Nuxt Nation 大会即将到来。加入我们,时间为 11 月 12 日至 13 日。

api-shield
nuxt-api-shield

Nuxt API Shield - 速率限制

Nuxt API Shield

npm versionnpm downloadsLicenseNuxt

此 Nuxt 模块实现了一个速率限制中间件,以保护您的 API 端点免受过多的请求。

功能

  • 基于 IP 的速率限制和暴力破解防护
    • 跟踪和执行单个 IP 地址的速率限制。
    • 防止恶意行为者或来自单个来源的过量请求压垮您的 API。
  • 可自定义的速率限制
    • 配置最大请求数、限制适用的持续时间以及超出限制的封禁时间段。
    • 当用户被封禁时,在响应中添加延迟以阻止进一步的滥用。
    • 自定义被封禁用户的错误消息。
    • 可以选择在用户被封禁时在响应中包含 Retry-After 标头。
    • 调整速率限制行为以符合您的 API 的特定需求和使用模式。
  • 事件驱动处理
    • 使用 Nuxt 的事件系统有效地拦截传入的 API 请求。
    • 确保与您的 Nuxt 应用程序的请求生命周期无缝集成。
  • 灵活的存储
    • 利用 Nuxt 的 unstorage 抽象实现多功能的存储选项。
    • 根据项目的需要,将速率限制数据存储在各种存储提供程序(文件系统、内存、数据库等)中。
  • 可使用运行时配置进行配置
    • 无需更改代码即可轻松调整速率限制参数。
    • 适应动态需求并通过 Nuxt 的运行时配置控制速率限制行为。
  • 清晰的错误处理
    • 当超出速率限制时,返回标准化的 429“请求过多”错误响应。
    • 促进客户端应用程序中的正确错误处理,以提供流畅的用户体验。

快速设置

1. 将 nuxt-api-shield 依赖项添加到您的项目中

# Using pnpm
pnpm add nuxt-api-shield

# Using yarn
yarn add nuxt-api-shield

# Using npm
npm install nuxt-api-shield

2. 将 nuxt-api-shield 添加到 nuxt.config.tsmodules 部分

您应该只添加您希望与默认值不同的值。

export default defineNuxtConfig({
  modules: ["nuxt-api-shield"],
  nuxtApiShield: {
    /*limit: {
      max: 12,        // maximum requests per duration time, default is 12/duration
      duration: 108,   // duration time in seconds, default is 108 seconds
      ban: 3600,      // ban time in seconds, default is 3600 seconds = 1 hour
    },
    delayOnBan: true  // delay every response with +1sec when the user is banned, default is true
    errorMessage: "Too Many Requests",  // error message when the user is banned, default is "Too Many Requests"
    retryAfterHeader: false, // when the user is banned add the Retry-After header to the response, default is false
    log: {
      path: "logs", // path to the log file, every day a new log file will be created, use "" to disable logging
      attempts: 100,    // if an IP reach 100 requests, all the requests will be logged, can be used for further analysis or blocking for example with fail2ban, use 0 to disable logging
    },
    routes: [], // specify routes to apply rate limiting to, default is an empty array meaning all routes are protected.
    // Example:
    // routes: ["/api/v2/", "/api/v3/"], // /api/v1 will not be protected, /api/v2/ and /api/v3/ will be protected */
  },
});

3. 将 nitro/storage 添加到 nuxt.config.ts

您可以使用任何您想要的存储,但您必须使用 **shield** 作为存储的名称。

{
  "nitro": {
    "storage": {
      "shield": {
        // storage name, you **must** use "shield" as the name
        "driver": "memory"
      }
    }
  }
}

4. 将 shield:clean 添加到 nuxt.config.ts

{
  "nitro": {
    "experimental": {
      "tasks": true
    },
    "scheduledTasks": {
      "*/15 * * * *": ["shield:clean"] // clean the shield storage every 15 minutes
    }
  }
}

5. 创建您的 clean 任务

server/tasks/shield/clean.ts 中,您应该拥有类似以下内容。

import type { RateLimit } from "#imports";

export default defineTask({
  meta: {
    description: "Clean expired bans",
  },
  async run() {
    const shieldStorage = useStorage("shield");

    const keys = await shieldStorage.getKeys();
    keys.forEach(async (key) => {
      const rateLimit = (await shieldStorage.getItem(key)) as RateLimit;
      if (isBanExpired(rateLimit)) {
        await shieldStorage.removeItem(key);
      }
    });
    return { result: keys };
  },
});

开发

# Install dependencies
yarn

# Generate type stubs
yarn dev:prepare

# Develop with the playground
yarn dev

# Build the playground
yarn dev:build

# Run ESLint
yarn lint

# Run Vitest
yarn test
yarn test:watch

# Release new version
yarn release:patch
yarn release:minor