Reputation: 645
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" />
Upvotes: 1
Views: 3187
Reputation: 26066
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.
Upvotes: 3