背景: わかりました。ninjawars.net でレガシー BBG を実行しています。フォーム ポストを介して初期化された、プレイヤーが他のプレイヤーに対して実行できる「攻撃」があります。基本的に、状況を単純化して、ページがあるふりをすることができます。それを attack.php と呼び、別の php ページに送信する巨大な「ATTACK」フォーム投稿を持ち、それを accept_attack.php と呼び、2 番目のページが攻撃を実行します。たとえば、他のプレイヤー 1、2、または 3 を倒すとします。サーバーは PHP5、Postgresql、Apache を実行します。
問題点:
- 大きな「ATTACK」ボタンを押して、accept_attack.php に移動すると、更新を 3 回押して、毎回再送信し、3 回続けて攻撃することができます。
- 最初のページの 3 つのタブを開き、各ページで攻撃をヒットすると、プレイヤー 1、2、3 を一度に殺す 3 つの瞬間的な攻撃が発生し、継続的に更新して繰り返すことができます。
- データベースに保存される「最新の攻撃」タイマーを作成しようと試みたにもかかわらず、プレイヤーはおそらく、コピーされた 3 つのタブを十分に同期された方法で更新するだけで、それを回避できるようです。タイマー (例: 10:00:00:0000 am) を取得し、結果の処理を続行します。
必要なソリューション:
では、特定のスクリプトの同じ処理が一度に 3 重に実行されるのを防ぐにはどうすればよいでしょうか。
Php、ソーシャル エンジニアリング、および/または javascript/jQuery ソリューションが推奨されます (おそらくこの順序で)。
編集:答えに基づいて、これを解決するために(おそらく、ストレステストの前に)私がしたことは次のとおりです。セッションの答えは、実装するのが最も簡単/最も理解しやすいように見えたので、そのデータストアを使用しました。私はそれをテストし、うまくいくように見えますが、私が気づいていない方法があるかもしれません.
$recent_attack = null;
$start_of_attack = microtime(true);
$attack_spacing = 0.2; // fraction of a second
if(SESSION::is_set('recent_attack')){
$recent_attack = SESSION::get('recent_attack');
}
if($recent_attack && $recent_attack>($start_of_attack-$attack_spacing)){
echo "<p>Even the best of ninjas cannot attack that quickly.</p>";
echo "<a href='attack_player.php'>Return to combat</a>";
SESSION::set('recent_attack', $start_of_attack);
die();
} else {
SESSION::set('recent_attack', $start_of_attack);
}
それを改善する方法、またはそれを悪用できる方法がある場合(エコーすることはロジックの適切な分離ではないことが私には明らかであることを超えて)、私は知りたい. .