prevent double posts
Moderator: General Moderators
prevent double posts
How do you guys prevent double submits on a form? Basically the form posts then header redirects, but it's possible a person could hit that submit button real quick and enter two records... the tables in the db are auto-increment nor are their any unique columns...
I've never used this approach to fix this exact problem, but I'd imagine it would work.
You could generate a single-use key and embed it as a hidden field in your form.
Basically, a random key is generated and inserted into your form. It is also saved into a SESSION.
Then when the form is processed, it checks the submitted key and if it matches, it processes the form. Once processed, the key is removed from the session.
When the second submission arrives, the key is missing and the form refuses to process.
Of course, you'd have to find a non-confusing way to let the user know. Maybe a redirect to the normal after-post page with a notice saying that a multiple or unauthorized post was detected - check to ensure post was successful.
This will also prevent other sites manufacturing forms to submit to your site.
A code snip from somewhere ...
Not my best code, but you can see the idea. The first function generates a time limited single-use code to be inserted into a form, and the second checks the session token against the returned token to ensure that it is the same and that the time limit of 300 seconds has not expired. Unlike me, but clearly I was returning failure codes - normally I wouldn't use 0 or 1 for this as they can evaluate to true or false, but anyhow - so it will return 0 on success, 1 for failed token and 2 for timeout.
Anyhow ... not saying this is the greatest code in the world, but it should point you in the right direction.
Hope this helps
EDIT | Just thought it would be fun to add the other function to create the token. At least it wasn't a totally forgotten email attachment, which is my usual slip-up
You could generate a single-use key and embed it as a hidden field in your form.
Basically, a random key is generated and inserted into your form. It is also saved into a SESSION.
Then when the form is processed, it checks the submitted key and if it matches, it processes the form. Once processed, the key is removed from the session.
When the second submission arrives, the key is missing and the form refuses to process.
Of course, you'd have to find a non-confusing way to let the user know. Maybe a redirect to the normal after-post page with a notice saying that a multiple or unauthorized post was detected - check to ensure post was successful.
This will also prevent other sites manufacturing forms to submit to your site.
A code snip from somewhere ...
Code: Select all
function new_token() {
$token = md5(uniqid(rand(), true));
$_SESSION['FORM_TOKEN'] = $token;
$_SESSION['FORM_TIME'] = time();
return $token;
}
function check_token($token) {
if(isset($_SESSION['FORM_TOKEN']) && isset($_SESSION['FORM_TIME'])) {
if((time() - $_SESSION['FORM_TIME']) <= 300) {
if($_SESSION['FORM_TOKEN'] == $token) {
unset($_SESSION['FORM_TOKEN']);
unset($_SESSION['FORM_TIME']);
return 0; // Success
} else return 1; // Failure - token invalid
} else return 2; // Failure - token timeout
}
return 1; // Failure - token invalid
}
Anyhow ... not saying this is the greatest code in the world, but it should point you in the right direction.
Hope this helps
EDIT | Just thought it would be fun to add the other function to create the token. At least it wasn't a totally forgotten email attachment, which is my usual slip-up
Well, my approach is not for that reason -- moreso security -- but it will work for that. And adds a layer of security to your web site.
I generate a random token.
I then store it in a hidden input field in the form.
Then I store the page and their user id in a database table.
Then when they submit the form, I check that the token exists in the database with the same credentials.
This:
a) Ensures the form submission came from my site.
b) Ensures the user posting the form has sufficient permissions to post the form.
and c) I guess it prevents double posting since once the form is processed, the token is removed from the database. If they tried to submit in the manner you mentioned, it would give them an error.
I generate a random token.
Code: Select all
$token = md5(microtime());Code: Select all
echo '<input type="hidden" name="token" value="' . $token . '" />';Code: Select all
mysql_query("INSERT INTO `tokens` (`token`, `page`, `user`) VALUES ('$token', '$page', '$userId')") or die(mysql_error());This:
a) Ensures the form submission came from my site.
b) Ensures the user posting the form has sufficient permissions to post the form.
and c) I guess it prevents double posting since once the form is processed, the token is removed from the database. If they tried to submit in the manner you mentioned, it would give them an error.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
- Kieran Huggins
- DevNet Master
- Posts: 3635
- Joined: Wed Dec 06, 2006 4:14 pm
- Location: Toronto, Canada
- Contact:
It wouldn't be. It was about two years ago when I designed my token system. Storage is storage, choose a method.Stryks wrote:Is there any real need to save a single use value to the database? Especially when the token system is best applied with a time limit?
Not nitpicking or anything, just wondering why that would be better than temp storage in a session.
Cheers
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
- Kieran Huggins
- DevNet Master
- Posts: 3635
- Joined: Wed Dec 06, 2006 4:14 pm
- Location: Toronto, Canada
- Contact:
scottayy: interesting
What if there is no userid? I would assume you use this token thingy on all forms, not just user specific. Then I guess you just don't fill in that user column.
But why would that guarantee to be post from your site?
Wouldn't it be possible to open page as usual...see the token...and forge request with valid token and spoofed form?
What if there is no userid? I would assume you use this token thingy on all forms, not just user specific. Then I guess you just don't fill in that user column.
But why would that guarantee to be post from your site?
Wouldn't it be possible to open page as usual...see the token...and forge request with valid token and spoofed form?
Sure, but it's a one time use token, so automation would be a bit hard. But, all of my forms I use the token on are when the user is logged in. So the combination check of the session for user id and the database for the token makes it pretty hard to fake it.jmut wrote:scottayy: interesting
What if there is no userid? I would assume you use this token thingy on all forms, not just user specific. Then I guess you just don't fill in that user column.
But why would that guarantee to be post from your site?
Wouldn't it be possible to open page as usual...see the token...and forge request with valid token and spoofed form?
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
Is there really a need to even have the hidden field? What if when the form was submitted, it added a token into session... but before doing that I check if the token exists, if it does exist this would mean they have already posted the form otherwise It would add it to session and move on to the next page, then when the form process is complete I just kill the session?
So... User hits submit button, I check if token exists, if it does, ignore the db call and simply hit the header redirect, if it doesn't exist, add it and redirect.
So... User hits submit button, I check if token exists, if it does, ignore the db call and simply hit the header redirect, if it doesn't exist, add it and redirect.
A database token allows you to check against something. But, storing the time the token was made in the session may be helpful too.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.