First, I realize that there are other questions asked that are similar to this one, but they do not contain any definitive solutions to my problem.
When a customer submits an order, I need to be able to properly prevent my processing script from running more than once for that particular order.
/payment - the customer fills in all of their details and submits the order
/process_order - collects all of the data and processes the order.
What is happening is that my orders are being processed partially and then processed again fully ... and I can only assume that this is because customers are either double-clicking on the submit button, or are clicking the submit button a second time because the process hasn't completed and the browser hasn't redirected to the 'thank you' page yet...
I could just use jQuery to disable the button upon the first click event, but I'd also like to know what I could do on the server side of things to prevent this from happening.
One possible solution is to create, essentially, a nonce token for your form and store it in the session when showing the form.
$_SESSION['formNonce'] = md5( time() . uniquid() );
When generating the form, add it as a hidden field:
<input type="hidden" name="formNonce" value="<?php echo($_SESSION['formNonce']); ?>">
And then when processing it, the first thing you do is validate the nonce is in the session and then remove it. In this way, a second submission won't pass the validation because the nonce token has been removed.
There would be some tweaking and error checking to all of this, but coupled with the javascript button disabling could be a viable solution.
For example, you can use "anti-forgery tockens" approach. Once user does visit a page, there is a tocken assigned. First attempts to submit the page will remove the tocken from valid list so further attempts would fail.
Related
I have a PHP form script which uses mail function. basically you write your email and the email to want to send the recommendation on the page to, and click send.
Here is the problem, once you have sent the recommendation, you can send it again, this time by refreshing the same page!
How can I make script to not remember the previous entered information by same user? flush() or something else. The script is placed in the middle of the page so I don't want the page stop executing after this php form.
Edit:
Thank you guys for your answeres, is there any script so I can use for for storing/validating IPs with help of mysql? or just a "plain text database"?
This is the web browser, not the form, that's causing this behaviour - when you refresh a page that was the result of a form submission, most browsers will offer to resubmit the data.
The usual "fix" is to submit the data to an intermediate page, then redirect the person back to the page they were viewing - that way they'd have to go back one page as well as refresh AND clicking "yes, I want to resubmit the data".
For completeness, consider only allowing a particular ip to use the "send to friend" function once per x seconds/minutes by tracking an IP's last use in a database.
For extra thoroughness, prevent a given recipient being told about a page more than once a day, or something.
Two different things you might experience:
The fact that when you go to your form the information entered previously is remebered. That is typically a function of the webbrowser (and/or the plugings installed) and not so much a problem of your script/form. That is a similar function to how your browser might remeber login credentials for you.
Typically that is not much of an issue, but you could prevent that by generating unique names for your input fields each time the form is loaded.
<input type=text name=email lenght=40>...
then becomes
<inut type=hidden uniqueID=$something>
<input type=text name=email-$something lenght=40>...
and then use the uniqueID in your form processor to reconstruct all other field names when processing the form.
Your second problem is simply that your form processor allows the same content to be processed twice or more. A common problem with common fixes.
A traditional strategy was to redirect the browser to a succes/error page after processing the form contents, which can be reloaded without any penalty. form --> formhandler page (PHP) processes form contents and sends http redirect --> success/error page.
Or more common nowadays, store the above uniqueID of the form (e.g. in a database) and refuse to process a second time.
I have a PHP application where users can apply for a bonus. But there is a confirmation page before the bonus redemption code runs.
The issue is that in IE, if you hit f5 right after you click the continue button, the confirmation page refreshes while the bonus redemption code had already been triggered by the continue button and actually goes through. But because the user still sees the confirmation page, they would hit the continue button again and now they get an error cause they are already registered.
Is there a way i can disable the f5 button using javascript? Is this the best way to go about this? I have tried many scripts i found online to do this, but none of them achieves it. Is there a better way I can go about this? Perhaps from the application side?
Edit: If the outcome of claiming a bonus is databased, you can load existing claims on your confirmation screen and test that one already exists.
Edit: the other neat trick you can do is serailize/json_encode the $_POST and produce a hash from this, store it in the database or user session, and test against it.
I would generate and database a single use token (hash) for the form as a hidden field, if post data is re-sumbited, the token would have already been consumed, and you can invalidate the post request.
There are couple of methods to solve your issue:
Checkout here: http://bjw.co.nz/developer/general/75-how-to-prevent-form-resubmission
I have been using second method (Using sessions) and it's really working well.
I have a form that processes a payment, but approximately one in every 300 payments comes though twice, my logs show that there were two requests for all these occurrences.
I implemented some JavaScript that disables the submit button after it's clicked, and it seems to work fine for me, but I'm still getting double submissions every now and then.
Does anyone know anything else that could be causing the form to be submitted twice?
As Dagon says, server-side checks are your friend here. Give each instance of the form a randomly generated key (guid would be nice), and store that in the database. Don't accept forms that contain a key that already exists in the db.
Also, are you simply displaying HTML after your form processing logic executes? If so, try redirecting after you process the form.
It is a way: after user presses form submit button, disable it with javascript. That should prevent user from double submitting the form accidently. It works for all sites we implement it like because. Because sometimes user gets impatient and clicks form submit button several times, thats why you get double requests. What you need to make sure it works for all the browsers (disabling the button I mean).
Also you could do it on server side, it just is harder.
We use similar to the upvoted answer in Enable/disable submit button with jQuery and Coldfusion server code
I'm currently developing a page where the user fills out a form, and when submitted they are taken to the next page. When on the next page, I want to have it so that if the user went back to the previous page using the back button, or hit refresh, the submission will not be saved into the DB.
Now I recall reading somewhere that if you had a way to make each submission unique, this issue is averted, but after screwing around for hours on end, for the life of me I cannot recall how this could be done (using PHP), so long story short has anyone ran into this, and if so, what was your solution?
Use the Post/Redirect/Get pattern to avoid this problem. See also Redirect After Post.
Another way is to generate an identifier using uniqid and include it in the form as a hidden input. On submission, store that identifier in a database column marked with a UNIQUE index. This will cause subsequent submissions to throw a SQL error, which your application can handle gracefully.
You can add any confirmation on the second page.
By adding any confirmation box or any button....
by which you can confirm that whether user want to save it or not....
and if you don't want any confirmation...then you can delete the last record....by using managing session...but it is not good practice to fire the query very soon and delete in that kind..
so best way will be by adding any confirmation msg....
What is the best way to stop a form from being reprocessed when a user hits a Back button?
I'm following the Post/Redirect/Get pattern, so I don't have a problem if F5 is pushed, but the back button still provides the opportunity to resubmit the form. If this form is a credit card processing page, this is bad.
This question has been asked somewhat here, but the phrasing and answers were of poor quality and not specific to this problem exactly.
I have form.php which submits to itself. If there were no errors in input data upon submission, the user is redirected to form_thanks.php. Hitting back (and "Send" or "Resubmit") once resubmits form.php (BAD!) and then brings them back to form_thanks.php.
Please also include solutions that do not involve using Sessions, if possible.
I would do it a different way. Put up a hidden input with a random string as the value, and when it's submitted store that random string in a session. Set up a simple check to see if they've already posted it and if they have don't accept the input.
This should be done with a single-use token, or a nonce. The php/server should include this token in a hidden form field.
It should store a list of all the recent tokens and each time a form is submitted, it should check to see if the token is in the list of recent valid tokens.
If it's not in the list, then don't reprocess the form.
If it is in the list, then process the form and remove the token from the list.
The tokens can be handled within sessions or just a simple database table without sessions. The tokens should be user-specific though.
This is also the recommended way to avoid CSRF attacks.
Just thinking out loud here. But what about a variation on post/redirect/get where the final get is not actually the final get ;) But rather, it in turn always automatically forwards to the truly final page, so that should the user hit the back button, they return right back whence they came?
EDIT:
Ok, taking into consideration the OP's comment, here's another idea. The URL for the form submission could be made to require a parameter that is good for only one use. That token would be generated (using MD5 or some such) before the form was submitted and could be stored in a database (in response to somebody else's suggestion you requested a solution without using sessions). After the form is processed, this token would then be flagged in the database as having already been used. So that when the page is returned to with the same token, steps can be taken to prevent the resubmission of the form data to the backend.
Late answer, but one could avoid the processing altogether by using an AJAX-based solution; there wouldn't be an issue with including a nonce with this processing scheme, but by using an asynchronous query which, on success, redirects the user, the requests are not repeated by refreshing, pressing back, or anything other than clicking the button.
It is also easy to implement a mechanism that prevents the button from either being pressed twice or being "locked up" if something happened during the request by embedding into the handler for the request (whether high level with PrototypeJS or jQuery or low level with your handrolled function) the mechanisms to enable and disable the button when the request completes and first fires, respectively.
I find that back will bring the form to the state it was before the page was redirected, if that is the case, have a hidden input/variable or something which starts with value say true, then once the form is submitted, and if the value is true, change it to false and then submit, else return false
Try this :
<SCRIPT type="text/javascript">
window.history.forward();
</SCRIPT>