11

ユーザーがAJAXを使用してというファイルにメッセージを送信するサイトがありますlike.php。このファイルでは、ユーザーメッセージがデータベースに送信され、リンクがユーザーに返送されます。私のJavascriptコードでは、ユーザーがAJAXリクエストを送信するときに入力するテキストボックスを無効にしました。

唯一の問題は、悪意のあるユーザーが常にPOST要求を送信しlike.phpて、データベースにフラッディングする可能性があることです。そこで、簡単な洪水防御を実装したいと思います。

ユーザーのIPなどをログに記録する別のデータベーステーブルの煩わしさを本当に望んでいません...まるで彼らが私のサイトを氾濫させているかのように、多くのデータベースの読み取り/書き込みがそれを遅くします。にデータを送信するたびにチェックされるタイムスタンプを含むセッションを使用することを考えましlike.phpた。現在の時刻がタイムスタンプより前の場合は、データベースにデータを追加します。それ以外の場合は、エラーを送信してブロックします。データベースへの入力が許可されている場合は、セッションを新しいタイムスタンプで更新します。

どう思いますか?これが最善の方法でしょうか、それとももっと簡単な方法がありますか?

助けてくれてありがとう。:)

4

7 に答える 7

7

セッションはこれを行うのが最も簡単で、オーバーヘッドも最小です。セッションには、最後の投稿のタイムスタンプと投稿の送信元のIPの2ビットのデータを保存できます。次に、正当性を確認する方法は次のとおりです。

session_start();
if(isset($_SESSION['ip']) && $_SESSION['last_post'] + MININTERVAL < time()) die('too early');

$_SESSION['last_post'] = time();
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
// store the message
于 2010-06-11T23:23:05.030 に答える
5

トークンを使用します。トークンを生成し、それをリクエストの発信元のページに追加します。リクエストに有効なトークンが含まれていることを確認します。like.phpつまり、外部のトークンが直接POSTするのではなく、ページから送信されます。

于 2010-06-11T22:42:07.117 に答える
3

これを行う別の方法は、jQueryを使用してページへの非表示のフォーム入力(like.phpを呼び出す)を書き込むことです。ボットはjavascriptを使用しないため、非表示のフォームフィールドは存在しません。

非表示のフィールドを確認し(値と名前を割り当てます)、存在する場合は、データベースにリクエストを送信します。

別の方法; 非表示の要素をページにコーディングします(<input style='display:none;' name='nospam' value='' />)。ボットはフォームのすべてのフィールドに自動入力するため、このフィールドにデータが入力されているかどうかを確認するだけです。ユーザーには表示されないため、コンテンツがあればボットであることがわかります。

jQueryを使用してスタイル(display:none;)を設定します...繰り返しますが、ボットはjQueryを認識しないため、これは正当なフォーム入力であると見なされます。

'このページを実行するにはjavascriptが必要です'ユーザーのどこかに通知を指定することをお勧めします。いくつかの代替案。結局のところ-あなたは「シンプル」と言った;)

于 2012-04-16T00:53:20.007 に答える
3

コアリクエストのみを処理するスクリプトを作成しました(セッションリクエストやコアを呼び出さないその他のリクエストはありません)。あなたがグーグルを見るならば、あなたは毎回高い負荷のためにあなたのサーバーを殺すであろうスクリプト/クラスを見つけるでしょう。多くの人がSESSIONを使用しており、SQL / Databaseも使用すると、サーバーキラーとしてフラッディング保護を利用できるようになります。また、SESSIONにはCookie(またはGET SID)が必要であるため、SESSIONを簡単に操作して新しいSESSIONIDを取得できます。

私の関数はテキストベースで、簡単な処理を行います。悪いことは、時々CronJobを使用してipsを削除しなければならないことです。他のスクリプトと比較すると、約10 *高速です(セッションよりも節約できます)。

それが本当に役立つかどうかはわかりません。;)rpm値を以下または/および200reqに変更したい場合があります。私の設定では、ボットが6秒未満でインターバルリクエストを実行することを禁止しています。

<?php
function ht_request_limiter() {
    if (!isset($_SERVER['REMOTE_ADDR'])) { return; } // Maybe its impossible, however we check it first
    if (empty($_SERVER['REMOTE_ADDR'])) { return; } // Maybe its impossible, however we check it first
    $path = '/your/path/ipsec/'; // I use a function to validate a path first and return if false...
    $path = $path.$_SERVER['REMOTE_ADDR'].'.txt'; // Real file path (filename = <ip>.txt)
    $now = time(); // Current timestamp
    if (!file_exists($path)) { // If first request or new request after 1 hour / 24 hour ban, new file with <timestamp>|<counter>
        if ($handle = fopen($path, 'w+')) {
            if (fwrite($handle, $now.'|0')) { chmod($path, 0700); } // Chmod to prevent access via web
            fclose($handle);
        }
    }
    else if (($content = file_get_contents($path)) !== false) { // Load existing file
        $content = explode('|',$content); // Create paraset [0] -> timestamp  [1] -> counter
        $diff = (int)$now-(int)$content[0]; // Time difference in seconds from first request to now
        if ($content[1] == 'ban') { // If [1] = ban we check if it was less than 24 hours and die if so
            if ($diff>86400) { unlink($path); } // 24 hours in seconds.. if more delete ip file
            else {
                header("HTTP/1.1 503 Service Unavailable");
                exit("Your IP is banned for 24 hours, because of too many requests.");
            }
        }
        else if ($diff>3600) { unlink($path); } // If first request was more than 1 hour, new ip file
        else {
            $current = ((int)$content[1])+1; // Counter + 1
            if ($current>200) { // We check rpm (request per minute) after 200 request to get a good ~value
                $rpm = ($current/($diff/60));
                if ($rpm>10) { // If there was more than 10 rpm -> ban (if you have a request all 5 secs. you will be banned after ~17 minutes)
                    if ($handle = fopen($path, 'w+')) {
                        fwrite($handle, $content[0].'|ban');
                        fclose($handle);
                        // Maybe you like to log the ip once -> die after next request
                    }
                    return;
                }
            }
            if ($handle = fopen($path, 'w+')) { // else write counter
                fwrite($handle, $content[0].'|'.$current .'');
                fclose($handle);
            }
        }
    }
}

編集:リクエスト時間をテストする私の方法は、マイクロタイムを使用して、10,000人のユーザーをシミュレートすることでした。私はグーグルに尋ねてテストしました(例として)http://technitip.net/simple-php-flood-protection-class

だから私はそこで何が単純であるべきか分かりませんか?次のように、一度に約3つのSQLリクエストがあります。

$this -> user_in_db($ip))
$this->user_flooding($ip);
$this->remove_old_users();

より多くの機能を提供するかもしれませんが、すべての正当なユーザーはサーバータイムを無料で使用します。;)

于 2012-05-04T16:13:04.253 に答える
3

レコードファイル全体を調べる必要はありません。その代わり:

<?php
define("FLOODPOOL", ".");
define("FLOODPOOL_LIMIT", 30);
define("FLOODPOOL_DURATION", 60 * 60 * 24);
define("FLOODPOOL_AUTOCLEAN", true);

// Record and check flood.
// Return true for hit.
function floodpool_check($id){
    $fp = fopen(FLOODPOOL . DIRECTORY_SEPARATOR . 'fp_' . basename($id), 'a+');
    fwrite($fp, pack('L', time()));
    if(fseek($fp, -4 * FLOODPOOL_LIMIT, SEEK_END) === -1) {
        return false;
    }
    $time = reset(unpack('L', fread($fp, 4)));
    fclose($fp);
    if(time() - $time < FLOODPOOL_DURATION) {
        if(FLOODPOOL_AUTOCLEAN){
            @floodpool_clean();
        }
        return true;
    }
    return false;
}


// Clean the pool.
function floodpool_clean(){
    $handle = opendir(FLOODPOOL);
    while(false!==($entry=readdir($handle))){
        $filename = FLOODPOOL . DIRECTORY_SEPARATOR . $entry;
        if(time() - filectime($filename) > FLOODPOOL_DURATION && substr($entry, 0, 3) === 'fp_'){
            unlink($filename);
        }
    }
    closedir($handle);
}

使用例:

if(floodpool_check($_SERVER['REMOTE_ADDR'])){
    header("HTTP/1.1 429 Too Many Requests");
    exit("Hit some *");
}
于 2015-03-30T08:13:38.267 に答える
1

検索ページのフラッディングを停止したい場合は、次のように試すことができます。

$flood_protection_interval = 2;
session_start();
if(
    isset($_SESSION['ip']) && 
    $_SESSION['counter'] > 10 &&
    $_SESSION['last_post'] + $flood_protection_interval > time()
    ){
        // $_SESSION['counter'] = 0; // Use this if you want to reset counter
        die("<pre>\n\n\n\t<b>FLOOD PROTECTION</b>");
}
$_SESSION['counter']++;
$_SESSION['last_post'] = time();
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];

したがって、訪問者が2秒以内に10回検索すると、訪問者は停止します。

于 2016-04-27T15:30:43.070 に答える
0

like.phpにデータを送信するたびにチェックされるタイムスタンプを含むセッションがあるように、セッションを使用することを考えました。

ボットはユーザーと同じCookieを送受信できるため、これによってボットが停止することはありません。

あなたは本当にそのようなシステムにログインするユーザーを持っているべきです。アクセスを保護する価値があるようです。IPごとに1分あたりの投稿を制限することも検討できますが、複数のボットが依然として多くのスパムメッセージを送信する可能性があります。

ログインを実装したくない場合は、多くのサイトがキャプチャを使用してそのような試みを削減しようとします。

http://www.phpcaptcha.org/

于 2010-06-11T22:32:12.257 に答える