如何防止在 PHP 中重复提交表单(跨多个窗口进行保护)?

Posted

技术标签:

【中文标题】如何防止在 PHP 中重复提交表单(跨多个窗口进行保护)?【英文标题】:How can i prevent duplicate form submission in PHP (that protects across multiple windows)? 【发布时间】:2012-03-25 07:05:59 【问题描述】:

我试过了:

POST/REDIRECT/GET 方法,但这不能防止同一表单的多个实例(例如,如果用户在两个单独的窗口中打开 form.php,并在窗口 1 中提交表单,他们可以仍然在窗口 2 中提交)

UNIQUE TOKEN 方法,该方法在加载表单时将 uid 生成到会话变量中,并在处理表单时取消设置,但如果用户打开了其他不同的表单,则从取消设置变量这些其他表格也是如此,因此它们被视为“已处理”。

【问题讨论】:

所以每个表单都有一个唯一的令牌会话。 如果您多次打开表单(尤其是在使用不同浏览器的情况下),您无法阻止这种情况……为什么他们还要多次打开表单?一旦提交按钮被点击,我就会禁用它,这样他们就不会意外提交两次。 我试过这样做,但是如果用户打开一个不同的表单,它会为会话分配一个新的令牌并使以前的表单无效 我看到你能意识到它是数据库驱动的唯一方法。但这需要用户标识 @toby 由于 datbaase 事务的性质,多次提交可能会失去完整性,所以我试图从各个方面对其进行密封。您的方法只是防止用户在同一页面上多次按下提交按钮。 【参考方案1】:

表单提交是否仅限于登录用户或网站访问者?

如果此表单仅适用于登录用户,您可以在表单到达您的控制器后立即检查他们的 user_id。您可以在表单处理时设置临时 cookie 或会话变量。表单完成后,您可以取消设置此会话变量。表单提交后,请检查此会话变量是否已设置(即他们是否已发送表单两次)。如果检测到此会话变量,则请求失败。

我想你可以对网站访问者做同样的事情,甚至可以使用表格来存储 IP 地址,但这有点过度和资源密集。

【讨论】:

【参考方案2】:

确定您只希望单次提交的表单。然后将您的唯一令牌添加为隐藏 ID,每次生成表单 html 并存储在会话中。这是您知道属于未处理组的所有有效 ID。只有一个提交会取消该组的所有其他 ID。这也意味着,当他在那之后打开其他几个表格时,他们开始创建新组。

此打开需要您拥有一个会话数组(或 db),其中包含属于未处理表单的所有 ID 的项目。一次只能保留一组。任何不在组中的 ID 都会被忽略/取消。

【讨论】:

【参考方案3】:

你看到用户“Ofir Baruch”的评论了吗?这对我来说似乎是正确的。

您只需将您已经尝试过的两种方法结合起来,正确使用,并且正如 Ofir baruch 所说,为每个表单设置一个唯一的令牌会话。

差不多是这样的:

form1.php

session_start();

if (empty($_SESSION['form_tokens']['form1']))

    $_SESSION['form_tokens']['form1'] = generate_random_token();


if (isset($_POST['token']))

    if ($_POST['token']) != $_SESSION['form_tokens']['form1'])
    
        // the token is invalid - do not process the form
        redirect('/some_page');
    
    else
    
        // process the form here
        if ($success)
        
            // reset the token for this form
            unset($_SESSION['form_tokens']['form1']);
            redirect('/another_page');
        
    


<form id="form1">
    <input type="hidden" name="token" value="<?php echo $_SESSION['form_tokens']['form1']; ?>" />
    <input type="submit" value="Submit" />
</form>

form2.php 中您也可以这样做,但使用其唯一标记:

$_SESSION['form_tokens']['form2']

如果您想阻止 ALSO 使用两种不同的浏览器 - 甚至是计算机 - 而这非常重要,那么您应该在另一个地方处理它 - 我的意思是,您不应该允许同一个用户可以有两个会话。有几种方法可以做到这一点,但这是另一个问题。

【讨论】:

以上是关于如何防止在 PHP 中重复提交表单(跨多个窗口进行保护)?的主要内容,如果未能解决你的问题,请参考以下文章

php 如何防止表单重复提交呢

php 在自己本身的页面如何防止重复提交的

JSONP解决跨域问题,防止表单重复提交,防止XSS攻击

如何防止在 PHP 中多次单击时提交多个表单

php通过记录IP来防止表单重复提交方法分析

php防止用户重复提交表单