PHP即使使用CSRF令牌也会在表单提交中重复订单


PHP duplicate orders in form submission even with CSRF token

对于用PHP编写的应用程序中的'确认订单'页面,我需要防止多个表单提交,这样我们就不会得到重复的订单。我尝试用两种方法来处理这个问题:

  1. 对于支持javascript的用户,提交按钮是禁用的点击
  2. 令牌与表单一起生成并存储在会话中。在第一次提交时对它们进行比较,并删除会话令牌。因此,没有匹配令牌的后续提交应被拒绝。这应该有防止CSRF攻击的额外好处。

我明白这两种做法都是相当标准的做法,但问题似乎仍然存在?与js禁用,如果我点击提交按钮几次,我将得到X个重复的订单。

这让我认为这个问题可能与配置有关。它托管在lighthttpd上,php是用cgi-fcgi编译的。我不完全确定这是否相关,但我很困惑,为什么现在这是可能的。

服务器代码如下(为了简洁而删去):

<?php
    $_SESSION['token'] = uniqid('', true);
?>
<form name="myform" action="confirm" method="POST">
  <!--.... -->
 <input type="hidden" name="csrftoken" value="<?php echo $_SESSION['token']; ?>" />
 <input type="submit" name="submit" />

然后在提交令牌时验证:

<?php
   if ($_POST['csrftoken'] == $_SESSION['token']) {
       //proceed and process order
       unset($_SESSION['token']);
   }
?>

会话启动,令牌正确生成,随后取消设置。

我过去使用过这种方法,没有任何问题,但这次它似乎仍然通过。

根据Ghigo的注释,我重构了代码以使其工作

这个问题最终是一个来自iframe和表单提交的会话锁定问题。确保尽早关闭会话是解决这个问题的关键。