有哪些方法可以防止表单中的双重发布? (PHP)

时间:2010-05-25 02:57:51

标签: php mysql

我想阻止用户意外发布评论两次。 我使用PRG(post redirect get)方法,以便将数据插入另一个页面,然后将用户重定向回显示注释的页面。这允许用户根据需要刷新多次。但是,当用户返回并再次单击提交或者他们点击提交100次非常快时,这不起作用。我不想要100条相同的评论。

我查看了SO上的相关问题,发现令牌最好。但我无法使用它。

//makerandomtoken(20) returns a random 20 length char. 

<form  method="post" ... >
<input type="text" id="comments" name="comments" class="commentbox" /><br/>
<input type="hidden" name="_token" value="<?php echo $token=makerandomtoken(20); ?>" />
<input type="submit" value="submit" name="submit"  />
</form>

if (isset($_POST['submit']) && !empty($comments)) 
{
    $comments= mysqli_real_escape_string($dbc,trim($_POST['comments']));

    //how do I make the if-statment to check if the token has been already set once?
    if ( ____________){ 
        //don't insert comment because already clicked submit
    }
    else{
        //insert the comment into the database
    }
}

所以我将令牌作为隐藏值,但是如何使用它来防止多次单击提交。

方法: 有人建议使用会话。我会将随机令牌设置为$ _SESSION ['_ token']并检查该会话令牌是否等于$ _POST ['_ token'],但我该怎么做?当我尝试时,它仍然没有检查

3 个答案:

答案 0 :(得分:6)

如果要阻止双重提交,则必须存储“已提交”与“未提交”的状态。您可以通过多种方式获取此信息。

  • 数据库 - 添加一个隐藏字段,其中包含一个唯一的自动生成值(您可以生成一个短随机字符串并附加当前时间)。如果您需要有状态的Web对话,此值还可用于标识对话。将此值添加到数据库并使其唯一。缺点:数据库中的冗余存储,评论插入的性能降低,必须生成唯一的字符串。
  • 会话 - 使用在类似事项中生成的值添加相同的隐藏字段。当用户提交表单时,如果该值尚未存在,请将其保存在会话中。如果是,那就是双重提交。缺点:您仍需要生成唯一令牌。
  • 浏览器 - (1)添加一些javascript以在点击后禁用提交按钮。 (2)具有以值0开头的隐藏字段,并在用户单击提交按钮时更改为1。如果用户再次单击该按钮,则检查该值是否为1并且如果是则中止。优点:没有独特的字符串。缺点:需要启用javascript;你可能还需要字符串才能实现有状态的网络对话。

答案 1 :(得分:0)

我会跳过整个随机令牌,只是在会话中存储(哈希)注释。如果它与会话中存储的现有值匹配,则删除注释。如果没有,请让它通过。显然存在问题:

  • 停止用户在不同的地方发布相同的评论。如果这是一个问题,请存储注释的哈希值以及它正在评论的事物的ID。
  • 用户可以按“返回”并提交不同的评论。我认为这是一个功能(它比删除注释更好,因为它匹配前一个注释的随机标记)。自动将其解释为评论编辑并不容易。
  • 如果用户在备用标签页中按“提交”,则无效。 (我认为这不太可能,并且它不需要存储多个随机令牌。)

你可能想要一个随机令牌来阻止XSRF,但这是另一个问题(在这种情况下,你要确保随机令牌与“它应该是什么”相同;我会存储一个长的 - 在会议中获得一个)。

另外,请考虑使用准备好的陈述。

答案 2 :(得分:0)

你也可以在jquery中做到非常简单。

$(document).on('click', '.className', function(){
    $(this).css( 'pointer-events', 'none' );
});