【Laravel11】アクセスレート制限

Laravel

Laravel8以降では、処理実行レート制限機能が搭載されています。

Rate Limiting - Laravel 11.x - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We???ve already laid the foundation ??? free...

この機能を利用して、一定期間内のアクセス数を制限する設定を施していきます。

これからやること

  • Laravelプロジェクト新規作成
  • レート制限設定
  • ルーティング
  • 動作確認

Laravelプロジェクト新規作成

新規プロジェクト「rate-limit」を作成します。

composer create-project laravel/laravel:^11 rate-limit

レート制限設定

「app\Providers\AppServiceProvider.php」を編集します。

冒頭に追記します。

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;

「boot()」メソッドにレート制限の設定を記述します。

    public function boot(): void
    {
        RateLimiter::for('top', function (Request $request) {
            return Limit::perSecond(1)
                ->by($request->user()?->id ?: $request->ip());
        });
    }

※「top」は設定の名称で好きに設定できます。

※「Limit::perSecond(1)」で1秒に1回までの制限です。

※「by()」でクライアントを特定するキーを設定します。

※ユーザーIDか、またはIPアドレスで特定する設定です。

※複数のレート制限設定をする場合は次のように「RateLimiter::for()」を羅列すればOKです。

    public function boot(): void
    {
        RateLimiter::for('top', function (Request $request) {
            return Limit::perSecond(1)
                ->by($request->user()?->id ?: $request->ip());
        });
        RateLimiter::for('support', function (Request $request) {
            return Limit::perHour(1)
                ->by($request->user()?->id ?: $request->ip());
        });
        RateLimiter::for('inquiry', function (Request $request) {
            return Limit::perDay(1)
                ->by($request->user()?->id ?: $request->ip());
        });
    }

▼完成形

<?php

namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        RateLimiter::for('top', function (Request $request) {
            return Limit::perSecond(1)
                ->by($request->user()?->id ?: $request->ip());
        });
    }
}

ルーティング

ルーティングで、エンドポイント毎にレート制限設定を適用できます。

「routes/web.php」(APIの場合は「routes/api.php」)

を編集します。

※「->middleware([‘throttle:top’])」を追記

<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
})->middleware(['throttle:top']);

※トップページ「/」に「top」のレート制限設定を適用

※エンドポイント毎に別のレート制限をする例は次のような感じです。

Route::get('/', function () {
    return view('welcome');
})->middleware(['throttle:top']);
Route::get('/contact/support', function () {
    return "サポート窓口です!";
})->middleware(['throttle:support']);
Route::get('/contact/inquiry', function () {
    return "お問い合わせ内容をどうぞ!";
})->middleware(['throttle:inquiry']);

動作確認

ビルトインサーバーを起動します。

php artisan serve

WEBブラウザで http://localhost:8000/ にアクセスします。

設定が1秒間に1回までなので、1秒間に2回以上アクセスしてみます。

※F5(または[Ctrl]+R)を連打します。

「429 TOO MANY REQUESTS」が表示されました。

設定できるレート制限

「Illuminate\Cache\RateLimiting\Limit」

(vendor/laravel/framework/src/illuminate/Cache/RateLimiting/Limit.php)

内のメソッドを見ると次のようになっています。

メソッド処理
perSecond()1秒間の制限回数設定を返す
perMinute()1分間の制限回数設定返す
perMinutes()指定分間の制限回数設定返す
perHour()1時間の制限回数設定返す
perDay()1日間の制限回数設定返す
none()無制限設定を返す

▼perSecond()

引数デフォルト説明
$maxAttemptsint1上限回数
$decaySecondsint12残りアクセス可能回数がリセットされるまでの秒数

▼perMinute()

引数デフォルト説明
$maxAttemptsint12上限回数
$decayMinutesint12残りアクセス可能回数がリセットされるまでの分数

※「$decayMinute」はPHPDoc上は「int」となっていますが、実装は型指定されていないので、「0.05」でも行けます。

    /**
     * Create a new rate limit.
     *
     * @param  int  $maxAttempts
     * @param  int  $decayMinutes
     * @return static
     */
    public static function perMinute($maxAttempts, $decayMinutes = 1)
    {
        return new static('', $maxAttempts, 60 * $decayMinutes);
    }

▼perMinutes()

引数デフォルト説明
$decayMinutesint2残りアクセス回数がリセットされるまでの分数
$maxAttemptsint12上限回数

※「perMinute(12, 2)」と「perMinutes(2, 12)」は同値です。

    /**
     * Create a new rate limit using minutes as decay time.
     *
     * @param  int  $decayMinutes
     * @param  int  $maxAttempts
     * @return static
     */
    public static function perMinutes($decayMinutes, $maxAttempts)
    {
        return new static('', $maxAttempts, 60 * $decayMinutes);
    }

▼perHour()

引数デフォルト説明
$maxAttemptsint720上限回数
$decayHoursint12残りアクセス回数がリセットされるまでの時間数

※「$decayHours」はPHPDoc上は「int」ですが、実装は型指定されていないので、「0.005」でもいけます。

    /**
     * Create a new rate limit using hours as decay time.
     *
     * @param  int  $maxAttempts
     * @param  int  $decayHours
     * @return static
     */
    public static function perHour($maxAttempts, $decayHours = 1)
    {
        return new static('', $maxAttempts, 60 * 60 * $decayHours);
    }

▼perDay()

引数デフォルト説明
$maxAttemptsint86400上限回数
$decayDaysint12残りアクセス数がリセットされるまでの日数

※「$decayDays」はPHPDoc上は「int」ですが、実装は型指定されていないので、「0.005」でもいけます。

    /**
     * Create a new rate limit using days as decay time.
     *
     * @param  int  $maxAttempts
     * @param  int  $decayDays
     * @return static
     */
    public static function perDay($maxAttempts, $decayDays = 1)
    {
        return new static('', $maxAttempts, 60 * 60 * 24 * $decayDays);
    }

▼none()

※引数なし

    /**
     * Create a new unlimited rate limit.
     *
     * @return static
     */
    public static function none()
    {
        return new Unlimited;
    }

※「Illuminate\Cache\RateLimiting\Unlimited」が返されます。

▼Illuminate\Cache\RateLimiting\Unlimited

<?php

namespace Illuminate\Cache\RateLimiting;

class Unlimited extends GlobalLimit
{
    /**
     * Create a new limit instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct(PHP_INT_MAX);
    }
}

※実際はPHPの整数上限値「PHP_INT_MAX」が設定されています。

PHP_INT_MAX (int)この PHP がサポートする整数型の最大値。32bit のシステムでは 通常は int(2147483647)。 64bit のシステムでは、int(9223372036854775807)。

参考サイト

Rate Limiting - Laravel 11.x - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We???ve already laid the foundation ??? free...
Save server resource in Laravel 11
How do you save server resource in Laravel 11?
https://www.elegantlaravel.com/article/per-second-rate-limiting-in-laravel-11
LaravelアプリケーションのAPIにレート制限を実装する方法
LaravelアプリケーションのAPIにレート制限を実装することで、アプリケーションリソースの大量消費を抑える方法をご紹介します。
  • 2
  • 0
  • 0
  • 0

コメント

タイトルとURLをコピーしました