Saturday, October 17, 2009

Prevent Duplicate Form Submission

Today Learn PHP Online will give you some basic tips on how to preventing duplicate form submission.

Duplicate Form Submissions

When a web form is submitted to a server through an HTTP POST request, a web user that attempts to refresh the server response in certain user agents can cause the contents of the original HTTP POST request to be resubmitted, possibly causing undesired results, such as a duplicate web purchase.

To avoid this problem, many web developers use the PRG pattern — instead of returning a web page directly, the POST operation returns a redirection command (using the HTTP 303 response code [sometimes 302] together with the HTTP "Location" response header), instructing the browser to load a different page using an HTTP GET request. A web user can then safely refresh the server response without causing the initial HTTP POST request to be resubmitted.

The PRG pattern cannot solve every way of duplicate form submission. Some known duplicate form submissions that PRG cannot solve are:

  • If a web user goes back to the web form and resubmits it.
  • If a web user clicks a submission button multiple times before the server response loads.
  • If a web user refreshes before the initial submission has completed because of server lag, resulting in a duplicate HTTP POST request in certain user agents.

Another way to prevent users from submitting forms twice (e.g. by double clicking a button) is to use Javascript to disable the button after the first click.

2 Ways to Prevent Duplicate Form Submissions

1) Using PHP sessions to prevent duplicate form submission.

<?php
session_start();

$_PG = (!empty($_POST)) ? array_merge($_POST, $_GET) : $_GET;
if(!empty($_PG)) {
 //Retrieve the value of the hidden field
 $form_secret=$_PG['form_secret'];
 if(isset($_SESSION['FORM_SECRET'])) {
  if(strcasecmp($form_secret,$_SESSION['FORM_SECRET'])===0) {
   echo "<br />Valid Key... Data was successfully saved.";
   unset($_SESSION['FORM_SECRET']);
  }else {
   //Invalid secret key
   echo "<br />Invalid Secret Key";
  }
 }else {
  //Secret key missing
  echo 'Form data has already been processed!';
 }
}
else
{
 $_SESSION['FORM_SECRET']=md5(uniqid(rand(), true));
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Prevent Duplicate Submission</title>
</head>

<body>

<form action="<?=$_SERVER['PHP_SELF']?>" >
    <input type="hidden" name="form_secret" value="<?php echo $_SESSION['FORM_SECRET'];?>" />
    <input type="submit" value="Submit" />
</form>

</body>
</html>

2) Using header() redirection technique. Suppose you have a form.php & action.php.

form.php
...
<form action="action.php" >
    <input type="submit" value="Submit" />
</form>
....

action.php
<?php

 // Your Logic function here example
 // mysql_query("INSERT ... values('{$_POST[0]}', ...)");

 // send back to the form.php page
 header("location: form.php");

?>

So, the flow would look like below.

FORM.PHP ---[submit form to]--> ACTION.PHP ---[submit back to]---> FORM.PHP


Source: http://en.wikipedia.org/wiki/Post/Redirect/Get

Related Posts




No comments:

Post a Comment