如何使用PHP会话来防止重复的表单提交?

时间:2017-01-18 22:21:34

标签: php forms session

我想停止向我的网页提交重复的表单。在我寻求帮助的任何地方,我看到使用$_SESSION变量;但我没有看到会话和表单如何在多个用户帐户的上下文之外可能相互连接。

有人能告诉我这个过程究竟是如何运作的吗?

编辑:我不想多次停止提交表单;仅防止重新提交具有相同值的表单(例如,在页面刷新上)。

处理完表单后,用户应该会看到成功/错误消息,然后再次看到该表单。

3 个答案:

答案 0 :(得分:2)

基本上你需要使用两次唯一的SESSION值。在表单中的某个地方,您尝试提交并存储在$ _SESSION变量中。当表单POSTED并且两个值都匹配时,我们成功提交,当表单POSTED但值不同时,不会提交。

即:

位于PHP页面顶部的某处:

    <?php
        session_start(); // first line of your PHP page
        $_SESSION['secretFormValue'] = isset($_SESSION["secretFormValue"]) ? $_SESSION["secretFormValue"] : md5(microtime()); // generate some unique session value

       // assign submitted **secretFormValue** from your form to a local variable
        $secretFormValue = isset($_POST["secretFormValue"])? filter_var($_POST["secretFormValue"], FILTER_SANITIZE_STRING) : '';

       // check if the value is present in the **secretFormValue** variable
        if($secretFormValue != '') {

           // check if both values are the same
           if($_SESSION["secretFormValue"] == $secretFormValue) {

                // Process form values & submission ...
                // add your own code...

                unset($_SESSION["secretFormValue"]);

           } else {

               echo "Duplicate submission";
           }

        } else {

           // do some other thing
        }

您表单中的某处:

<input type="hidden" name="secretFormValue" value"<?php echo $_SESSION['secretFormValue']; ?>">

***我没有对此进行测试,所以如果有错误,请发表评论,thx。*

修改 如果您需要阻止提交页面刷新,您可以包括在成功提交时清除所有POST值,因此刷新将因为空的POST而失败,例如:

unset($_POST); // place it right before unset($_SESSION["secretFormValue"]);

在提交后包括重定向到不同页面(即感谢页面),即:

header("Location:ThankYouPage.php"); // place it right after unset($_SESSION["secretFormValue"]);

或者刚刚在其他SO帖子中找到了这个:

https://en.wikipedia.org/wiki/Post/Redirect/Get

答案 1 :(得分:0)

您可以在访问者提交表单后设置$_SESSION['submittedForm'] = true;变量。然后,您可以在下次访问表单页面时检查该会话数据,并且不显示该表单,或者如果他们尝试再次提交该表单,则会抛出错误消息。

答案 2 :(得分:0)

我建议一种替代方法。您要解决的问题有两个变体:

  1. 当用户提交后刷新页面时,如何防止/检测到多次提交表单(通常是偶然)?
  2. 如何防止表单数据不是来自页面上显示的实际表单的提交(至少使表单变得更困难)?

Milan的解决方案可以解决这两个问题,但会单独产生一个问题:如果用户在多个选项卡/窗口中打开了同一页面(请记住,他们共享相同的会话),则会中断。

如果您不关心问题2,则通过在会话数据中保留已提交的表单ID列表,可以更轻松地执行“被动”方法:

$formID = (isset($_POST["__form_id"]) ? $_POST["__form_id"] : false);
$submittedforms = (isset($_SESSION["submittedforms"]) ? $_SESSION["submittedforms"] : array());

// Check whether this form ID has been submitted before
if (in_array($formID, $submittedforms)) {
    printf("Duplicate submission.");
    exit;
}

// Store the ID of this form submission
$submittedforms[] = $formID;
$_SESSION["submittedforms"] = $submittedforms;

// Continue form processing...

如果您还需要阻止未经授权(自动)的表单提交,则需要一种主动的方法。我将扩展Milan的解决方案,然后在会话数据(数组)中存储多个表单ID,每个生成的表单一个。然后在提交时将它们一一删除。