Question

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.

Was it helpful?

Solution 2

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.

OTHER TIPS

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.

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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top