php
Web
レートリミット(レート制限)とは特定のユーザから短時間に多すぎるリクエストがきた ときに機能の制限を設ける機能である。サーバに高負荷の処理が足りすぎるのを防ぐほか、 パスワード認証を様々なパスワードで叩きまくって突破を試みるブルートフォース攻撃などへの 初歩的な対策としても機能する。
PHPではLaravelなどのフレームワークを使えば比較的に簡単に設定できるのだが、 生PHPでやるとなるとちょっとしたコードが必要となる。安いレンタルサーバなどLaravel環境のセットアップが そもそもしにくいときにはこのようにやる手がある。
>?php // 設定 // 60秒間に5回まで許可 $limit = 5; $window = 60; $ip = $_SERVER['REMOTE_ADDR']; // クライアントIPアドレスをキーにする // ファイル名(IPアドレスごとにログを分ける) $file = sys_get_temp_dir() . "/rate_limit_" . md5($ip) . ".txt"; // 初期化 if (!file_exists($file)) { file_put_contents($file, json_encode(['count' => 0, 'timestamp' => time()])); } // ファイルの内容を読み込み $data = json_decode(file_get_contents($file), true); $now = time(); // 60秒過ぎていたらリミット解除 if ($now - $data['timestamp'] > $window) { $data = ['count' => 0, 'timestamp' => $now]; } $data['count']++; // 制限を超えた場合はエラーを返す if ($data['count'] > $limit) { // リクエスト数で接続拒絶するときは429を返すのが行儀が良い http_response_code(429); echo "Too Many Requests. Try again later."; exit; } // 更新したデータはファイルに落とす file_put_contents($file, json_encode($data)); // 正常処理 echo "Request allowed. You have used {$data['count']} of {$limit} requests."; // デモなのでlimitまでの残りリクエスト数を表示、本当は隠したほうが良いかも ?<この例では
- ユーザはIPアドレスをキーとして見分けることとする:同IPアドレスと別ユーザは巻き添えを食う
- リミットがかかったかはファイルで記憶;ここでRedisなどを使えばさらにパフォーマンスが良い
サンプル:1分5リクエストの制限がかかったページ
ここに5回連続でアクセスすると、6回目にはBANされていることが確認できる(笑)。 再度試したいときは60秒で解除されるので、少し待ってみていただきたい。
動作確認した環境
- さくらのレンタルサーバ ライト
- PHP 5.4.45
おすすめ記事
PHPでログインページ①PHPでログインページ①
HTML5で立ち絵展示用Canvas