防止发送php页面功能的垃圾邮件

Kzq*_*qai 2 javascript php spam-prevention concurrent-processing

背景:好的,我在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);
}
Run Code Online (Sandbox Code Playgroud)

如果有方法可以改进那些或可利用的方式(除了对我来说显而易见的事情,回应的东西不是一个很好的逻辑分离,我很想知道.沿着这些方向,社区维基编辑.

God*_*eke 7

虽然womp的Post-Redirect-Get模式将解决一些问题,如果他们故意游戏提交过程,那么我怀疑它会阻止问题,除了反对懒惰(如链接文章中所述,302响应之前的提交将是多个因为重定向尚未发生).

相反,您可能最好在攻击页面上放置一些不易复制的信息令牌.当您接受攻击时,将攻击推送到数据库队列表中.具体来说,在排队时存储发送到攻击页面的信息令牌,并在排队攻击之前检查该令牌是否已被使用.

一个简单的令牌来源是运行随机数生成器并将它们放入表中的结果.为每个攻击页面加载提取下一个数字,并验证该数字最近是否已分发.您可以在攻击页面加载时重新填充令牌,并根据您的策略使"未使用"令牌到期,以便在"过时"之前页面可用多长时间.

通过这种方式,您可以生成一组有限的"有效"令牌,在攻击页面上发布这些令牌(每页一个),并验证它们是否已在攻击处理页面上使用过令牌.为了创建重复攻击,玩家必须确定哪些令牌有效...重复相同的帖子将失败,因为令牌已被消耗.使用BigInt和一个体面的伪随机数生成器,搜索空间使它不太容易规避.(注意,您需要围绕令牌验证和更新的事务,以确保使用此方法成功.)

如果您有需要登录的用户帐户,则可以在用户表上生成并存储这些令牌(同样,使用围绕这些步骤的数据库事务).然后,每个用户一次只能有一个有效的令牌,并且会以类似的方式捕获多个提交.