背景:好的,我在 ninjawars.net 上运行了一个传统的 BBG。玩家可以对其他玩家进行“攻击”,该“攻击”是通过表单发布初始化的。本质上,我们可以简化情况,假设有一个页面,我们称之为attack.php,有一个巨大的“ATTACK”表单提交到另一个php页面,我们称之为accept_attack.php,第二个页面执行攻击功能,可以说杀死其他玩家 1、2 或 3。服务器运行 PHP5、Postgresql、Apache
问题:
- 如果我点击那个大的“ATTACK”按钮,它会把我带到accept_attack.php,然后我可以点击刷新三次,每次重新提交,连续攻击三次。
- 如果我打开第一页的三个标签,并在每一页上点击攻击,我最终会得到三个瞬时攻击,同时杀死玩家 1、2 和 3,我可以不断刷新重复。
- 尽管我尝试将“最近的攻击”计时器保存到数据库中,但玩家似乎能够解决它,也许只需以足够同步的方式刷新三个复制的选项卡,以便他们都可以检索到相同的计时器(例如上午 10:00:00:0000),然后继续进行结果处理。
需要的解决方案:
那么如何防止对某个脚本的相同处理一式三份地同时执行呢?
首选 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);
}
如果有改进的方法或者可以利用的方法(除了对我来说很明显的那个,回声的东西不是一个很好的逻辑分离,我很想知道。沿着这些思路,社区维基编辑.