0

I have a php sign up process for uses. When the user gets to the second last page of the sign-up process, it shows a summary of all the signup details and the submit button(Confirm and Pay button basically). Now when the user clicks this button, all those details gets posted to the sql database and that user is created in the DB with a username and password. Now the problem is, if you click that submit button more than once, it resubmits the data and creates duplicate entries in the database, where each duplicate entry has the same details(name, email etc), but different usernames and passwords. How do I prevent this? I know you can submit and postback to self right after but how do I do that exactly? I tried to implement this code but it does not work: http://www.bjw.co.nz/developer/general/75-how-to-prevent-form-resubmission

Thanks

DextrousDave
  • 6,603
  • 35
  • 91
  • 134
  • 1
    I've never done anything like that with forms, but I assume the easiest way to do it would be to create a form key upon loading the form for the first time, and saving that key either in a file or a database. When the form is submitted, it should post the key, and the receiving php script should then remove that key from the file or database of valid keys. – FThompson May 11 '12 at 15:11
  • Have you tried disabling the submit button – Ahmed Jolani May 11 '12 at 15:11

4 Answers4

3

I would advise a bit of JavaScript in this situation. Add the following to the submit button:

onclick="this.disabled=true;"

This will disable the button once it is clicked so that it can't be clicked again.

Ashley Strout
  • 6,107
  • 5
  • 25
  • 45
  • Does not work when Noscript is used. Though a combination of this and what I suggested would be working great. Stackoverflow really needs composite answers :) – sinni800 May 11 '12 at 15:13
  • Well if a user is smart enough to have noscript installed, they should also be smart enough not to click submit buttons twice. – Ashley Strout May 11 '12 at 15:14
  • 1
    99% of your users will have javascript working.the ones that have noscript installed will understand how a form submit works – clem May 11 '12 at 15:15
  • @David I would probably say that I am smart enough not to click twice, but I had a mouse before that clicked twice sometimes (sic!) when I only clicked once. I dispatched of it as soon as I had a new one... But that double clicking brought me some massive stress for a while. – sinni800 May 11 '12 at 15:15
  • You can't discount malicious users. Someone could attempt to exploit your system with a simulated form post. – Nate May 11 '12 at 15:16
  • @stratton I wouldn't say that. I know enough people which just got Noscript suggested and now they just go along with it... Without even knowing jack – sinni800 May 11 '12 at 15:16
  • It's a matter of fractions or possibilities. Are you worried enough about double submissions that you'll cater to that tiny fraction of users that has noscript installed along with a wonky mouse? Malicious users are a possibility, though. What I suggested was just meant as a quick and easy fix. – Ashley Strout May 11 '12 at 15:18
  • You can put the input inside an anchor tag and href the anchor to # so double clicks won't work. – Ahmed Jolani May 11 '12 at 15:19
  • @David it depends on what kind of site he runs. If it's a webshop then... I'd do it for the 0.1%. Well, I'd do it always anyway – sinni800 May 11 '12 at 15:24
  • But there are always malicious users, and if they're determined, they'll find security holes elsewhere. That I can almost guarantee. This is just some user creation, so what if an extra is created 0.1% of the time? Have some sort of cron job run that will weed those out. – Ashley Strout May 11 '12 at 15:25
  • @ everyone. Thank you for your answers. Will test these out and rate your answers...However, I'm not so worried about the uninformed users out there, but more the malicious users, who can create multiple accounts with multiple advantages, exploiting the advantages with each of those accounts – DextrousDave May 14 '12 at 09:44
  • @DextrousDave yes it supposed to dig in the answers they provided more in order to come up with a better solution. – Ahmed Jolani May 14 '12 at 16:20
3

You should save a value into the PHP session that identifies if the form is already submitted, using $_SESSION. The PHP Session is locked while each request carries out, so when the first submit locks it, the second will have to wait until the first submit is finished and has set the value. The second request will afterwards read it, and break upon the value being set to already submitted.

Here's an example of how this could be done. It could probably incorporate bugs if one user is doing several registrations at once (why should he?).

On the page that contains the submit button of the form, you should set a marker:

session_start();
$_SESSION["RegistrationSubmitted"] = false;

This says that the registration that a user is currently doing has not been submitted yet.

On the page that is being submitted (POSTed) to, you can check this value:

session_start();
if (isset($_SESSION["RegistrationSubmitted"]) {
    if ($_SESSION["RegistrationSubmitted"] == true) {
         die("Registration has already been submitted!");
    } else {
         // Process registration here
         $_SESSION["RegistrationSubmitted"] == true;
    }
} else {
    die("Last registration page hasn't been reached! (A bot?)");
}
sinni800
  • 1,451
  • 14
  • 29
  • Thanks for your answer, but the problem is this: I know php, but not this well. So I don't know how to create this. I tried this example: http://www.bjw.co.nz/developer/general/75-how-to-prevent-form-resubmission, and also calling in the help of a guy that knows php, and he could implement this either. Do you perhaps have a sample code/snipped? Would appreciate. I would like to mark your answer as the solution, but if I can't get it to work, then I'll have to go with David's javascript solution – DextrousDave May 14 '12 at 09:49
  • I tried your code but couldn't get it to work. What works for me: I just check in the database of the user details already exist before submitting the form to poke in new user details: $get_new_user = mysql_query("SELECT * FROM pp_signup WHERE name = '$name' AND email = '$email' AND method = '$method' AND plan = '$plan' AND mobile = '$mobile' AND handset = '$handset'", $joomla_sqlconnection); $data_new_user = mysql_fetch_array($get_new_user); if ($data_new_user['id'] == "") { .From thereon, it the $data_new_user['id'] is empty, only then will the form submit and poke in the new values. – DextrousDave May 15 '12 at 15:00
  • Well, um... How about, in this case, you just use @EmmanuelG's solution? INSERT IGNORE seems pretty good here. – sinni800 May 15 '12 at 15:14
1

Aside from messing with the PHP code or the DOM, why not modify your database table to use unique keys. This way regardless of how many times the user clicks a submit button, the database simply wont care.

This may help you: “INSERT IGNORE” vs “INSERT … ON DUPLICATE KEY UPDATE”

Community
  • 1
  • 1
EmmanuelG
  • 1,051
  • 9
  • 14
  • I'd say the best answer from an architectural standpoint. But that would mean that people should deviate from the usual "AUTO_INCREMENT" schema. Letting the database handle things like this IS always a good choice though. Enforcing consistency rules through the program code is just so.. ugly. I've met many people who just used the database to store, not verify it's contents :D – sinni800 May 11 '12 at 15:19
0

You could create a form key like:

<input type="hidden" name="form-key" value="<?php echo $last_order_datetime; ?>" />

Then, when a new order is submitted, check if the value of $_POST['form-key'] is exactly equal to the most recent order stored.

If it is, process the form. else, it is a resubmit or some other attempt.

Nate
  • 1,303
  • 8
  • 12
  • The value can be manipulated using inspect element, client Side validation should never be used. – Ahmed Jolani May 11 '12 at 15:17
  • The validating is done on the Server. They could change the value to whatever they wanted and unless it matched the most recent order it would fail – Nate May 11 '12 at 15:18
  • @Nate Is `$last_order_datetime` from the user's standpoint and not from the whole website? Also: What if one request comes in 10 seconds late due to... circumstances? I know, just give it a tolerance :D – sinni800 May 11 '12 at 15:22
  • $last_order_datetime would be from the user's standpoint. If another order comes in later then it would have the most recent orders datetime value instead. – Nate May 11 '12 at 15:40