Thursday 17 May 2012

Prevent resubmission of POST contents in PHP


How to prevent POST contents being resubmitted again and again when user refreshes the page?


This is much easier to explain with an example situation instead of generalized statement.

Example Situation

In Filename: input.php
<form action="process.php" method="POST">
Topic Title: <input type="text" name="title" /><br/>
Message: <input type="text" name="message" /><br/>
<input type="submit" />
</form>

In Filename: process.php

<?php


// process the contents of $_POST and then post a topic on user's behalf


...
...


// Show acknowledgement to user


?>

Flow

* (input.php) User submits Topic Title and Message in the input boxes and clicks on submit button.
* (process.php) POST content is processed and topic is posted.

The problem

After the user posted the topic content, she would land on process.php. If she refreshes the page now, the post content will be submitted again. If she does that again... again.... again and again... the topics will keep on getting posted with the same content. This can be done by users by mistake as well as intentionally.

Solutions

* Redirecting the user to other page instantly after POST is submitted.
* Adding Tokens

Redirection on process.php (updated code)

In Filename: process.php
<?php


// process the contents of $_POST and then post a topic on user's behalf


...
...


// Redirect User
header("Location: success.php");
exit;


?>


Further: Adding tokens (MySQL method)


Create a MySQL table called 'tokens' with only 3 fields: id (int(10)), token (varchar(32)), time (int(10))

In Filename: input.php (updated)
<form action="process.php" method="POST">
Topic Title: <input type="text" name="title" /><br/>
Message: <input type="text" name="message" /><br/>
<?php
$token=md5(mictrotime(true).mt_rand(1,9999)); // generate unique token
$res=mysql_query("INSERT INTO tokens SET token='$token', time='".time()."'");
?>
<input type="hidden" name="token" value="<?php echo $token; ?>" />


<input type="submit" />
</form>



In Filename: process.php
<?php


$TOKEN_EXPIRY=1800; //in seconds


$token=preg_replace('/[^w]/', '', $_POST['token']); //sanitize token
$active_tokenid=mysql_fetch_array(mysql_query("SELECT id, time FROM tokens WHERE token='$token'"));


if($active_tokenid[0]!='' && time()-$active_tokenid[1]<$TOKEN_EXPIRY){
$res=mysql_query("DELETE FROM tokens WHERE time<'".(time()-$TOKEN_EXPIRY)."'"); //cleanup old entries
// Redirect User
header("Location: expired.php");
exit;
}


// process the contents of $_POST and then post a topic on user's behalf


...
...


// Redirect User
header("Location: success.php");
exit;


?>

No comments:

Post a Comment