ひでメモ

プログラムについて勉強したことを書きます。たぶん。

【Laravel】レート制限の判定方法とホワイトリストのやり方

記事はたくさんあるんですがコードを見てへ~となったのでメモです。
あとうちのプロジェクトで実装している簡易ホワイトリストの実装も。

概要

プロジェクトではログイン処理がN分内にM回試行されると一時的なロックをかけるようにしています。(もちろんセキュリティのためです)
そのロック処理に Laravel のレート制限ミドルウェアを使用しているのですが、そもそも何を基準にロックしてるんだっけ?という話になり少し調べてみました。

レート制限の基準

以下を見ると接続先のドメイン名とIPアドレスを連結した後にハッシュ化した値でカウントしているようです。
(認証前の場合。認証後は User ID などになるはず)

protected function resolveRequestSignature($request)
    {
        if ($user = $request->user()) {
            return sha1($user->getAuthIdentifier());
        } elseif ($route = $request->route()) {
            return sha1($route->getDomain().'|'.$request->ip());   // ドメイン名とIPをつなげてハッシュ
        }

        throw new RuntimeException('Unable to generate the request signature. Route unavailable.');
    }

github.com

特定のIPアドレスだけレート制限をかけない

開発や検証のために特定のIPアドレスだけ制限をかけないようにしたいということはあると思います。
障害発生時に弾かれていたら大変ですし、普段でも仕事に支障が出るかもしれないです。

そこで、以下のように ThrottleRequests ミドルウェアを少し拡張してホワイトリストに登録したIPアドレスはレート制限の判定をスルーするようにしています。

use Illuminate\Routing\Middleware\ThrottleRequests as ThrottleRequestsOrigin;

class ThrottleRequests extends ThrottleRequestsOrigin
{
    public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1, $prefix = '')
    {
        // 許可されたIPは判定を行わない
        if (in_array($request->ip(), config('throttle.whitelist_ip'))) {
            return $next($request);
        }

        // ホワイトリストに該当しないIPアドレスは継承元にそのまま流す
        return parent::handle($request, $next, $maxAttempts, $decayMinutes, $prefix);
    }
}

ホワイトリストには自社やお客さんの運営担当などのIPアドレスを登録しています。
今のところ数も多くないため config に直接記載しています。