Skip to content

レート制限

レート制限はトークン発行インターフェースの悪用(ブルートフォース攻撃など)を防止するために使用します。

動作原理

トークンバケットアルゴリズムを使用し、指定した時間ウィンドウ内で各キーあたりの最大リクエスト数を制限します。

text
Create(claims) → レート制限キーを抽出 → RateLimitProvider を確認 → 許可/拒否

設定

go
cfg := jwt.DefaultConfig()
cfg.SecretKey = "hmac-key-that-has-at-least-32-bytes!"
cfg.EnableRateLimit = true
cfg.RateLimitRate = 100              // ウィンドウあたりの最大リクエスト数
cfg.RateLimitWindow = time.Minute    // 時間ウィンドウ
フィールドデフォルト値説明
EnableRateLimitfalseレート制限を有効にするかどうか
RateLimitRate100ウィンドウあたりの最大リクエスト数
RateLimitWindow1m時間ウィンドウ

注意

レート制限はすべてのトークン発行メソッドに適用されます:Create()CreateRefresh()Refresh()RefreshInto()Validate()ValidateInto() には影響しません。

レート制限キー

レート制限はキーごとに独立して適用されます。キーの検索優先順位は以下の通りです:

  1. RegisteredClaims.Subject — 空でない場合
  2. *Claims.UserID — 内蔵 Claims のみ
  3. RateLimitKey()RateLimitKeyer インターフェースを実装している場合
  4. 空文字列 — レート制限チェックをスキップ

カスタムレート制限キー

go
type MyClaims struct {
    UserID string `json:"user_id"`
    Email  string `json:"email"`
    jwt.RegisteredClaims
}

// RateLimitKeyer インターフェースの実装
func (c *MyClaims) RateLimitKey() string {
    return c.Email
}

内蔵 RateLimiter

NewRateLimiter で独立したレートリミッターを作成できます:

go
limiter := jwt.NewRateLimiter(100, time.Minute)

if limiter.Allow("user:123") {
    // 許可
} else {
    // 拒否
}

limiter.Reset("user:123") // カウントをリセット
defer limiter.Close()

カスタムレートリミッター

RateLimitProvider インターフェースを実装します:

go
type RateLimitProvider interface {
    Allow(key string) bool
    Reset(key string)
    Close()
}

AllowN について

インターフェース自体は単一判定の Allow のみを定義します。バッチ判定メソッド AllowN(key string, n int) bool は具象型 *RateLimiter の拡張メソッドであり、このインターフェースには属しません。

例えば Redis を使用した分散レート制限の実装:

go
cfg.RateLimiter = &RedisRateLimiter{client: rdb}

レート制限の超過

リクエストがレート制限のしきい値を超えると、トークン発行メソッド(Create()CreateRefresh()Refresh()RefreshInto())は ErrRateLimitExceeded を返します:

go
token, err := processor.Create(claims)
if errors.Is(err, jwt.ErrRateLimitExceeded) {
    // レート制限の処理:429 Too Many Requests を返す
}

次のステップ