Laravelでレート制限を使って大量アクセスを防ぐ方法

Laravelでレート制限を使って大量アクセスを防ぐ方法

640 回閲覧されました

みなさんこんにちは、jonioです。

現在個人開発を公開するに当たって色々とセキュリティを入れている最中ですがお問い合わせのページでロボットを使って何度もお問い合わせするといったイタズラを防ぐ方法がないかを調べました。

そしたらあっさり見つかったのでアウトプットとしてこの記事を残します。

Laravelのバージョン

バージョンは8です。

レート制限

今回のやり方は1分間でのアクセスの回数を制限します。

これによって何度も送信するのを防ぐことができます。

RouteServiceProvider.php

「Laravelのプロジェクト > app > Providers > RouteServiceProvider.php」に追記します。

<?php

namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;           //追加する
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to the "home" route for your application.
     *
     * This is used by Laravel authentication to redirect users after login.
     *
     * @var string
     */
    public const HOME = '/home';

    /**
     * The controller namespace for the application.
     *
     * When present, controller route declarations will automatically be prefixed with this namespace.
     *
     * @var string|null
     */
    protected $namespace = 'App\\Http\\Controllers';

    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @return void
     */
    public function boot()
    {
        $this->configureRateLimiting();

        $this->routes(function () {
            Route::prefix('api')
                ->middleware('api')
                ->namespace($this->namespace)
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));
        });
    }

    /**
     * Configure the rate limiters for the application.
     *
     * @return void
     */
    protected function configureRateLimiting()
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
        });

        //ここから追加
        RateLimiter::for('contact', function (Request $request){
            return Limit::perMinute(1);
        });
        //ここまで追加
    }
}

8行目は最初からあるかもしれません。

64行目〜67行目は追記します。

64行目の「contact」ですがここには好きな名称を入れます。

65行目の「perMinute(1)」ですが「1」は1分間に許可するアクセス回数です。

今は1にしているのでアクセス回数は1回ということになります。

web.php

次は設定をルーティングに追記します。

「Laravelのプロジェクト > routes > web.php」に追記します。

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});


//ここから追加
Route::middleware(['throttle:contact'])->group(function(){
    Route::post('/contact/store','ContactController@store')->name('contact.store');
});
//ここまで追加

22行目〜24行目を追記しています。

22行目の「contact」はRouteServiceProvider.phpで設定した名称です。

名称をcontactで設定していました。

動作確認

web.phpを見ると「http://localhost/contact/store」に1回しかアクセスできません。

画面読み込みを連続で2回しました。

すると下記の画面になりアクセスできないのが確認できます。

これで実装が完了しました。