I found many questions on SO regarding the question how to prevent double form submission:
- How to prevent multiple form submission on multiple clicks in PHP
- How to handle multiple submissions server-side
- Preventing double form submissions
The answer seems to be:
- Disable the submit button as soon as the user clicks it.
- Follow a POST-Redirect-GET pattern to prevent POSTs when the user refreshes the page
- Prevent double submission on the server side when JS is disabled.
I am interested how step 3 can be implemented. I found here
The common solution is to generate a token on the server every time you generate a form. Store the token on the server, add it as a hidden field to the form, and delete it once you get a form submission with that token.
If you get a form submission without a valid token, it means that the form has already been submitted and ignore it.
An example implementation of this may be found here:
function isTokenValid($token){
if(!empty($_SESSION['tokens'][$token])){
unset($_SESSION['tokens'][$token]);
return true;
}
return false;
}
// Check if a form has been sent
$postedToken = filter_input(INPUT_POST, 'token');
if(!empty($postedToken)){
if(isTokenValid($postedToken)){
// Process form
}
else{
// Do something about the error
}
}
However, I do not understand why this should work. If a user clicks a button twice (and we have no JS disable button protection), then I believe its possible that both requests are executed parallel. If the validation check happens simultaneously then both request would pass on the server side.
The only way I can image to prevent this is by using a database with transactions. But is it really that complicated? Or am I overlook something?