更新: レート制限に sleep() を使用しないでください! これはまったく意味がありません。私は手に良い解決策を持っていません。
ログイン試行が失敗した直後から始めるのが良いでしょsleep(1);う - 実装が簡単で、ほとんどバグがありません。
人間にとって 1 秒は大した時間ではありません (特に、人間によるログイン試行は頻繁に失敗しないため)。辞書攻撃は別の問題かもしれませんが、同じドメインにあります。
攻撃者がこれを回避するためにあまりにも多くの接続を開始した場合、一種の DOS 攻撃に対処します。問題は解決しました (しかし、別の問題が発生しました)。
あなたが考慮すべきいくつかのもの:
- IP ごとにのみアカウントをロックすると、プライベート ネットワークに問題が発生する可能性があります。
- ユーザー名だけでアカウントをロックすると、既知のユーザー名に対するサービス拒否攻撃が可能になります
- IP /ユーザー名ベース(ユーザー名が攻撃されるもの)でロックすると、よりうまく機能する可能性があります
私の提案:
完全なロックは望ましくない(DOS)ため、より良い代替手段は次のとおりです。一意のIPから特定のユーザー名のログイン試行をカウントします。あなたは単純なテーブルでこれを行うことができますfailed_logins: IP/username/failed_attempts
ログインが失敗した場合、wait(failed_attempts);秒。xx 分ごとに、failed_logins:failed_attempts1 ずつ減少する cron スクリプトを実行します。
申し訳ありませんが、既製のソリューションを提供することはできませんが、これは簡単に実装できるはずです。
わかった、わかった。疑似コードは次のとおりです。
<?php
$login_success = tryToLogIn($username, $password);
if (!$login_success) {
// some kind of unique hash
$ipusr = getUserIP() . $username;
DB:update('INSERT INTO failed_logins (ip_usr, failed_attempts) VALUES (:ipusr, 1) ON DUPLICATE KEY UPDATE failed_logins SET failed_attempts = failed_attempts+1 WHERE ip_usr=:ipusr', array((':ipusr' => $ipusr));
$failed_attempts = DB:selectCell('SELECT failed_attempts WHERE ip_usr=:ipusr', array(':ipusr' => $ipusr));
sleep($failed_attempts);
redirect('/login', array('errorMessage' => 'login-fail! ur doin it rong!'));
}
?>
免責事項:これは特定の地域では機能しない場合があります。私が最後に聞いたのは、アジアでは国全体が NAT されているということでした (また、彼らは皆カンフーを知っています)。