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「Too Many Requests」エラーレスポンスを返します。
    • スムーズなユーザーエクスペリエンスのために、クライアントサイドアプリケーションでの適切なエラー処理を容易にします。

迅速なセットアップ

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.config.tsmodulesセクションにnuxt-api-shieldを追加します。

デフォルト値と異なる値のみを追加する必要があります。

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. nuxt.config.tsnitro/storageを追加します。

任意のストレージを使用できますが、ストレージの名前としてshieldを使用する必要があります。

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

4. nuxt.config.tsshield:cleanを追加します。

{
  "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