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

时间:2013-03-20 08:47:48

标签: php duplicates token csrf lighttpd

对于用PHP编写的应用程序中的“确认订单”页面,我需要阻止多个表单提交,因此我们不会收到重复的订单。我试图以两种方式处理这个问题:

  1. 对于支持javascript的用户,禁用提交按钮 点击
  2. 使用表单生成令牌并存储在会话中。在第一次提交时,他们进行了比较,并删除了会话令牌。因此,应拒绝后续提交而没有匹配的令牌。这应该具有防止CSRF攻击的额外好处。
  3. 据我所知,两者都是相当标准的做法,但这个问题似乎仍然存在?如果我多次单击提交按钮,则禁用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']);
       }
    
    ?>
    

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

    我过去使用过这种方法没有任何问题,但这一次似乎仍然可以通过。非常感谢任何见解。

1 个答案:

答案 0 :(得分:0)

根据Ghigo的评论,我重构了代码以使其发挥作用。

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