Question

I have tried the method suggested on this site to prevent duplicate form submission, but I always get error Invalid secret key! after form should be submitted (the form passed validation). What can the problem be?

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" />
Was it helpful?

Solution

In the example you link to the author suggests doing this:

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

But in your example you are doing this:

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

Note that in the original, the === comparison operator is being used, but in yours you are using ==.

Also, in your form, does the value for form_secret ever actually get set when you do this:

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

It seems to me that without knowing the larger structure of your form HTML & PHP this is hard to debug. But I have an idea based in the fact our PHP has this:

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

But the form is then processed below that. All that will do each time is reset the value of $_SESSION['FORM_SECRET']. Instead that chunk of code needs to be with your HTML form page. Maybe something like this:

<?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" />

And then in your PHP to process the form this should be the only session related line:

<?php
  .
  .
  .
  session_start();

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

The whole idea is that the <input type="hidden" name="form_secret"… is set with the $secret = md5(uniqid(rand(), true)); value when passed into $_SESSION['FORM_SECRET']. And then the session_start(); allows your PHP to pick up the value of $_SESSION['FORM_SECRET'] & act on it.

The idea being that the form has a hidden form_secret value & the $_SESSION['FORM_SECRET'] has a similar secret setting. And the fact that the HTML form creates a new value for that on each load of the form page allows you to do comparison between what is embedded in the form in a hidden value & the session itself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top