For a 'Confirm Order' page in application written in PHP I need to prevent multiple form submissions so we don't get duplicate orders. I have attempted to handle this in two ways:
- For users supporting javascript the submit button is disabled on click
- A token is generated with the form and stored in session. On the first submit they're compared and the session token is removed. Subsequent submissions without a matching token should therefore be rejected. This should have the added benefit of preventing CSRF attacks.
I understand that both are fairly standard practice, yet the issue seems to remain? With js disabled if I click the submit button several times I will get X number of duplicate orders.
This makes me think that perhaps the issue is config related. It is hosted on lighthttpd and php is compiled with cgi-fcgi. I;m not entirely sure if that is even relevant but I am baffled as to how this is now possible.
The server code is as follows (cut down for brevity):
<?php
$_SESSION['token'] = uniqid('', true);
?>
<form name="myform" action="confirm" method="POST">
<!--.... -->
<input type="hidden" name="csrftoken" value="<?php echo $_SESSION['token']; ?>" />
<input type="submit" name="submit" />
Then on submit the token is verified:
<?php
if ($_POST['csrftoken'] == $_SESSION['token']) {
//proceed and process order
unset($_SESSION['token']);
}
?>
Session is started and the token is correctly generated and subsequently unset.
I have used this approach in the past with no problems but this time round it still seems to get through. Would appreciate any insight.