透過 100 多個技巧的集合來學習 Nuxt!

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