防止重复表单提交

时间:2014-04-06 00:29:42

标签: php forms submit form-submit duplicate-removal

我已尝试the method suggested on this site以防止重复提交表单,但在提交表单后(表单通过验证)我总是收到错误Invalid secret key!。问题是什么?

PHP:

    <?php
      .
      .
      .
      session_start();
      $secret = md5(uniqid(rand(), true));
      $_SESSION['FORM_SECRET'] = $secret;

      // Send Message
      if (isset($_POST['send']))
      { 
            $name = strip_tags(trim($_POST['name']));
            $email = strip_tags(trim($_POST['email']));
            $subject = strip_tags(trim($_POST['subject']));
            $message = strip_tags(trim($_POST['message']));

            $valid_name = $name=='' || (mb_strlen($name) > 2 && preg_match('/^\p{L}+$/u', $name));
            $valid_email = filter_var($email, FILTER_VALIDATE_EMAIL);
            $valid_subject = $subject!='';
            $valid_message = $message!='';

        if ($valid_name && $valid_email && $valid_subject && $valid_message) {

          $form_secret = isset($_POST['form_secret'])?$_POST['form_secret']:'';

          if(isset($_SESSION['FORM_SECRET'])) {
            if(strcasecmp($form_secret, $_SESSION['FORM_SECRET']) == 0) {

                sendEmail($name, $email, $name, $email, $subject, $message, $support_email);
                $PAGE_MESSAGE = "Message has been sent!";           
                unset($_SESSION['FORM_SECRET']);

            } else {
              //Invalid secret key
              $PAGE_ERROR = "Invalid secret key!";
            }
          } else {
            //Secret key missing
            $PAGE_ERROR = "Form data has already been processed!";
          }  

        } else {
          $PAGE_ERROR = "Error (not valid)!";
        }
      }                 
    }       
  ?>

HTML:

    <form enctype="multipart/form-data" method="POST"> 
    <input type="hidden" name="form_secret" id="form_secret" value="<?php echo $_SESSION['FORM_SECRET'];?>" />
    .
    .
    .
    <input type="submit" name="send" value="Send" />

1 个答案:

答案 0 :(得分:3)

example you link to作者建议这样做:

if(isset($_SESSION["FORM_SECRET"])) {
    if(strcasecmp($form_secret, $_SESSION["FORM_SECRET"]) === 0) {

但在你的例子中,你这样做:

if(isset($_SESSION['FORM_SECRET'])) {
    if(strcasecmp($form_secret, $_SESSION['FORM_SECRET']) == 0) {

请注意,在原始版本中,正在使用===比较运算符,但在您的正在使用==

此外,在您的表单中,执行此操作时form_secret的值是否实际设置为:

<input type="hidden" name="form_secret" id="form_secret" value="<?php echo $_SESSION['FORM_SECRET'];?>" />

在我看来,如果不知道表单的大型结构,HTML&amp; PHP这很难调试。但我的想法基于我们的PHP有这个:

session_start();
$secret = md5(uniqid(rand(), true));
$_SESSION['FORM_SECRET'] = $secret;

但是表单会在下面处理。每次执行的操作都会重置$_SESSION['FORM_SECRET']的值。而是需要将大量代码与HTML表单页面放在一起。也许是这样的:

<?php 
session_start();
$secret = md5(uniqid(rand(), true));
$_SESSION['FORM_SECRET'] = $secret;
?>
<form enctype="multipart/form-data" method="POST"> 
<input type="hidden" name="form_secret" id="form_secret" value="<?php echo $_SESSION['FORM_SECRET'];?>" />
.
.
.
<input type="submit" name="send" value="Send" />

然后在PHP中处理表单,这应该是唯一与会话相关的行:

<?php
  .
  .
  .
  session_start();

  // Send Message
  if (isset($_POST['send']))
  { 

整个想法是<input type="hidden" name="form_secret"…在传递到$secret = md5(uniqid(rand(), true));时设置为$_SESSION['FORM_SECRET']值。然后session_start();允许您的PHP获取$_SESSION['FORM_SECRET']&amp;的价值采取行动。

这个想法是表单隐藏form_secret值&amp; $_SESSION['FORM_SECRET']具有类似的秘密设置。事实上,HTML表单在表单页面的每个负载上为其创建了一个新值,这使您可以在隐藏值和表单中嵌入表单中的内容进行比较。会议本身。