7

失敗した試行に基づいてログイン試行を抑制できるようにしたいのですが、いくつか質問があります。

MySQL を使用する必要がありますか? (DB に負担がかかる可能性があることをお読みください)
ユーザーごとに、システム全体またはシステム全体だけで調整する必要がありますか? (一般の人がパスワードを推測するのを防ぐため)
しきい値はどのように計算すればよいですか? (そのため、変更/成長に自動的に適応します)
このしきい値を取得するにはどうすればよいですか? 失敗するたびにクエリ/計算するか、キャッシュに保存しますか?
スロットルには何を使用すればよいですか? (スリープ()がサーバーに負担をかける可能性があるという応答を読んでください)

誰かサンプルコードを持っていますか?

私はこれにかなり慣れていないので、助けていただければ幸いです!ありがとう

4

3 に答える 3

6

私はAPC だけを使用してphunctionに貧乏人のスロットリング メカニズムを実装しました。

// allow 60 requests every 30 seconds
// each request counts as 1 (expensive operations can use higher values)
// keep track of IPs by REMOTE_ADDR (ignore others)

$throttle = ph()->Throttle($ttl = 30, $exit = 60, $count = 1, $proxy = false);

if ($throttle === true)
{
    // IP exceded 30 requests in the last 60 seconds, die() here
}

else
{
    // $throttle is a float
    // number of requests in the last 30 seconds / 30 seconds

    /*
     1 req / 30 = 0,033 sec
     5 req / 30 = 0,166 sec
    10 req / 30 = 0,333 sec
    15 req / 30 = 0,5   sec
    20 req / 30 = 0,666 sec
    25 req / 30 = 0,833 sec
    30 req / 30 = 1     sec
    */

    usleep(intval(floatval($throttle) * 1000000));
}

これを Front-Controller で使用し、値をルーティング メソッドに渡しますが、それは別の話です。

要するに、APC を使用すると、APC は FILO 方法論に従っているため、メモリ内で非常に高速に動作し、ほとんどメモリを消費しないということです。より高いタイムアウトが必要な場合は、メモリベースではないものを使用することを検討してください。

ところで: MySQL は MEMORY エンジンを使用したテーブルをサポートしています。


問題sleep()

モジュールとして PHP がインストールされた典型的な Apache Web サーバーは、インスタンスごとに約 10 MB の RAM を消費します。使用可能な RAM を超えないようにするために、Apache が起動できるインスタンスの最大数を制限するように構成できる Apache 設定がいくつかあります。

問題はsleep()、そのインスタンスがまだアクティブであり、十分なリクエストがあると、新しいサーバーを起動するために使用可能なすべてのスロットを消費してしまい、保留中のリクエストが完了するまで Web サイトにアクセスできなくなる可能性がある場合です。

PHPの知る限り、これを克服する方法はないため、最終的にはあなた次第です。


原則は、システム全体のスロットリングと同じです。

function systemWide($ttl = 86400, $exit = 360)
{
    if (extension_loaded('apc') === true)
    {
        $key = array(__FUNCTION__);

        if (apc_exists(__FUNCTION__) !== true)
        {
            apc_store(__FUNCTION__, 0, $ttl);
        }

        $result = apc_inc(__FUNCTION__, 1);

        if ($result < $exit)
        {
            return ($result / $ttl);
        }

        return true;
    }

    return false;
}
于 2011-02-18T02:54:40.017 に答える
2

失敗したログイン試行を次のような表に記録します。

FailedLogins
id
timestamp
ip

ユーザーがログインを試みるたびに、そのユーザーの IP アドレスで過去 Y 秒間に X 回のログイン試行の失敗があるかどうかを確認します。

ユーザーが Y 秒以内に X 回失敗した場合、エラー メッセージまたは CAPTCHA を表示します。

于 2011-02-18T02:58:28.307 に答える
1

MySQL データベースは 1 秒あたりのリクエスト数を処理できるため、何千人ものユーザーがいない場合でもボトルネックを心配する必要はありません。

sleep() を使用することもできます 注: PHP は ASP.NET よりも多くのユーザーを処理します。何千人ものユーザーがいない場合は、ボトルネックのないスリープ メソッドを使用できます。

私が通常行う方法は、ログイン試行 (IP、ユーザー ID、およびタイムスタンプ) を保存することです。テーブルに収納し、気が向いたときに(サイズや時間帯に)テーブルをリセットします。userID + IP が「一定の時間」内に「ログイン試行回数」を超えた場合、ユーザーをページにリダイレクトし、ユーザーが何度も試行したためにログインできないことを伝えます。次の15分(またはあなたが好きなもの)。私が推測するように少し「Windows」ですが、それは魅力のように機能します:)

于 2011-02-18T02:54:28.067 に答える