You want to prevent a user from submitting the same form more than once.
Insert a unique ID into a form
Example 9-24 checks the submitted token against saved data in an SQLite database to see if the form has already been submitted.
Checking a form for resubmission
For a variety of reasons, users often resubmit a form. Usually it's a slip-of-the-mouse: double-clicking the Submit button. They may hit their web browser's Back button to edit or recheck information, but then they re-hit Submit instead of Forward. It can be intentional: they're trying to stuff the ballot box for an online survey or sweepstakes. Our Solution prevents the non-malicious attack and can slow down the malicious user. It won't, however, eliminate all fraudulent use: more complicated work is required for that.
The Solution does prevent your database from being cluttered with too many copies of the same record. By generating a token that's placed in the form, you can uniquely identify that specific instance of the form, even when cookies are disabled. The uniqid( ) function generates an acceptable one-time token. The md5( ) function doesn't add any additional randomness to the token, but restricts the characters that could be in it. The results of uniqid( ) can be a mix of different letters and other characters. The results of md5( ) consist only of digits and the letters abcdef. For English-speaking users at least, this ensures that the token doesn't contain any naughty words.
It's tempting to avoid generating a random token and instead use a number one greater than the number of records already in your database table. There are (at least) two problems with this method. First, it creates a race condition. What happens when a second person starts the form before the first person has completed it? The second form will then have the same token as the first, and conflicts will occur. This can be worked around by creating a new blank record in the database when the form is requested, so the second person will get a number one higher than the first. However, this can lead to empty rows in the database if users opt not to complete the form.
The other reason not do this is because it makes it trivial to edit another record in the database by manually adjusting the ID to a different number. Depending on your security settings, a fake get or post submission allows the data to be altered without difficulty. A random token, however, can't be guessed merely by moving to a different integer.
9.13.4. See Also
Recipe 20.9 for more details on verifying data with hashes; documentation on uniqid( ) at http://www.php.net/uniqid and on md5( ) at http://www.php.net/md5.