Reputation: 707
This is what I want to do:
Prevent a user to submit a form twice using a unique token. I think I have the right code here, but it still dosn't work. The output is "Don't send twice" the first time the form is submitted. What am i doing wrong?
<?php session_start(); ?>
<html>
<body>
<?php
$_SESSION['token'] = md5(session_id() . time());
?>
<?php
if (isset($_SESSION['token']))
{
if (isset($_POST['token']))
{
if ($_POST['token'] != $_SESSION['token'])
{
echo "Don't send twice!";
}
}
}
else {
echo "Thank you for submitting";
}
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
<input type="text" name="bar" />
<input type="submit" value="Save" />
</form>
Upvotes: 0
Views: 2722
Reputation: 1676
Thank you for submitting
will never be displayed, because the condition for if( isset($_SESSION['token']) )
is always fulfilled, because you generate the token and set the session variable directly above this if clause... That's also why you will always see "don't send twice" after submitting the first time.
When loading the form you generate a token, save it in the session, put it in the form.
After submitting the form, you start the script again from the top:
Your token is now in the post variable. But you recreate your session token. then you compare post and session. of course they don't match, because you have just now generated a NEW token, so of course they are not equal.
I recommend this structure for your code:
<html>
<body>
<?php
session_start();
//HAS THE FORM BEEN SUBMITTED?
if(isset($_POST))
{
//THE FORM HAS BEEN SUBMITTED
//VALIDATE THE TOKEN
if($_POST['token'] == $_SESSION['token'])
{
//THE TOKEN WAS VALID, CONTINUE WITH PROCEDURES
}
else
{
echo 'Invalid token, please try again!';
}
}
else
{
//FORM NOT SUBMITTED YET
$token = $_SESSION['token'] = md5( session_id() . time(). rand() );
//i recommend adding rand() otherwise there is always a 1 second window in which the token could be doubled up...
echo '<form action="'. $_SERVER['PHP_SELF'] .'" method="post">';
echo '<input type="hidden" name="token" value="'. $token .'" />';
echo '<input type="text" name="bar" />';
echo '<input type="submit" value="Save" />';
echo '</form>';
}
?>
</body>
</html>
Upvotes: 1
Reputation: 19895
The concept here is flawed.
Browsers don't let the user submit a form twice using POST. They show an alert to the user telling about the danger to submit the form twice.
If the user loads the form twice, this script cannot avoid two submission, because the tokens are different on both forms.
I would suggest to save the submission in the database. This assures that the same session ( or the same user ) can only save one record.
Upvotes: 1