4

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.

Community
  • 1
  • 1
philfreo
  • 41,941
  • 26
  • 128
  • 141
  • Why do you want to implement this without sessions? You will probably need *some* kind of server-side storage to detect the duplicate post. – staticsan Oct 29 '09 at 23:40
  • See below where I suggest storing a token in a database along with whether or not its been used yet. This is definitely *some* kind of server-side storage, but not sessions. – Dexygen Oct 30 '09 at 00:19

6 Answers6

7

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.

Whitey
  • 153
  • 2
  • 5
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.

philfreo
  • 41,941
  • 26
  • 128
  • 141
  • Hmm, I'm surprised you can answer your own questions on SO. Should most likely just `UPDATE` your main question to include the solution. – Jakub Nov 17 '09 at 21:10
  • "It's also perfectly fine to ask and answer your own question" ( http://meta.stackoverflow.com/faq ) and it was suggested that I do this once someone else's answer didn't seem to fully answer the question. It's best to do this in separate questions/answers because that way other people can specifically comment/vote on them and because otherwise the original "question" is confusing for people who find it since it's no longer a question. – philfreo Nov 18 '09 at 00:27
1

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.

Dexygen
  • 12,287
  • 13
  • 80
  • 147
  • That would work except for the fact that browsers' back buttons often have dropdowns that let a user easily jump 2 or more pages back. – philfreo Oct 29 '09 at 23:56
  • Under my second suggestion, every time the URL is requested without a token parameter, a token is generated and the form essentially redirects to itself but with this token as part of the URL. Hope this is making sense, I've been up since 5:30 am ;) – Dexygen Oct 30 '09 at 00:32
  • For the sake of this Question page, perhaps someone should mark a comprehensive answer involving sessions and session-less database tokens. – philfreo Oct 30 '09 at 03:37
  • Phil: you could always answer the question that way yourself – Dexygen Oct 30 '09 at 10:05
1

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.

Dereleased
  • 9,939
  • 3
  • 35
  • 51
0

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

Psytronic
  • 6,043
  • 5
  • 37
  • 56
-1

Try this :

<SCRIPT type="text/javascript">
    window.history.forward();
</SCRIPT>
Stephan
  • 41,764
  • 65
  • 238
  • 329
zphp
  • 1
  • 1
  • This is a PHP question, not javascript. – Avada Kedavra Oct 02 '12 at 08:05
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient [reputation](http://stackoverflow.com/faq#reputation) you will be able to [comment on any post](http://stackoverflow.com/privileges/comment). – Avada Kedavra Oct 02 '12 at 08:05
  • I have tried above code in my online exam page (**PHP**) .Which prevented the action of back button,I know its against rules to disable back button . There is no point if the candidate can go back and answer the question again(in the case of online exam ). It worked for me . – zphp Oct 03 '12 at 04:29