20

I am working on a web application (J2EE) and I would like to know the options that are available for handling a double post from the browser.

The solutions that I have seen and used in the past are all client-side:

  • Disable the submit button as soon as the user clicks it.
  • Follow a POST-Redirect-GET pattern to prevent POSTs when the user clicks the back button.
  • Handle the onSubmit event of the form and keep track of the submission status with JavaScript.

I would prefer to implement a server side solution if possible. Are there any better approaches than the ones I have mentioned above, or are client-side solutions best?

Roman C
  • 49,761
  • 33
  • 66
  • 176
Rontologist
  • 3,568
  • 1
  • 20
  • 23

7 Answers7

11

Its hard to implement an idiot-proof solution (as they are alway improving the idiots). No matter what you do, the client side can be manipulated or perform incorrectly.

Your solution has got to be server side to be reliable and secure. That said, one approach is to review the request and check system/database state or logs to determine if it was already processed. Ideally, the process on the server side should be idempotent if possible, and it will have to protect against dupe submits if it can't be.

Joe Skora
  • 14,735
  • 5
  • 36
  • 39
9

You could supply a "ticket" as part of the form, some random number - and make sure it doesn't get accepted twice, on the server side.

zigdon
  • 14,573
  • 6
  • 35
  • 54
  • How do you handle a user pressing the back button (most browsers don't re-request), changing the data in the form, and submitting the same "ticket" again? – JeremyWeir Aug 19 '10 at 23:13
  • 4
    You can't stop the user from resubmitting a new request with the same ticket, but you can reject it on the server side, with a "Duplicate request" error. – zigdon Aug 19 '10 at 23:28
  • Right, but people do that on purpose - submit a form, press back because they know they need to correct something, submit form again. Their legitimate usage of the browser's back button to edit a record would result in an error. – JeremyWeir Aug 20 '10 at 17:35
  • 2
    Sure, and if it's a legit pattern than you can add support for it - on the server side, find their previous request (with the same ticket), and update the information as needed. It's your call how long you're willing to accept changes to the form, of course. – zigdon Aug 20 '10 at 18:03
  • if the submission was completed fully, you should disable the token, or if the submission was made partly, you should allow the token to be re-used, handling the partly submitted details at the same time. – abel Oct 07 '10 at 14:14
  • So, ticket will be created **per get request to the form OR per form load**, am I right? but what if the user refreshed the page(another get req, another new ticket)...how to handle this? – Mehraj Malik Dec 29 '17 at 18:18
5

Two server-side solutions come to mind:

  1. Create one-time use "tokens" in a hidden form field. Once a token is used, it is deleted from whatever database or session context object you're storing it in. The second time, it's not accepted.
  2. Cache information received, and if an identical form is received within a certain time period (10 minutes? an hour? You decide!) it is ignored.
Josh Hinman
  • 6,745
  • 7
  • 38
  • 47
  • 1. How do you handle a user pressing the back button (most browsers don't re-request), changing the data in the form, and submitting the same token again? 2. What if within the time period the form is submitted with a value A, then the user changes it to have value B, then change it back to value A again? Wouldn't that ignore the last change? – JeremyWeir Aug 19 '10 at 23:15
3

we use a time sensitive, one time ticket. It's like a session id of sort. But it is tied to the form/page.

You discard the ticket when the user submits the page, and you only process pages that comes with a valid ticket. You can, at the same time, tighten security by attaching the ticket to a user, so tat if a ticket comes in that is submitted by a user that is not the user that the ticket was submitted to, you reject the request.

paan
  • 7,054
  • 8
  • 38
  • 44
2

Implement a uniqueid to go with the request and log it along with the execution. If the id was already logged, you don't do the job again. This is kinda like the fallback solution - you should try and disable the button or link clientside as well as you suggested yourself

Per Hornshøj-Schierbeck
  • 15,097
  • 21
  • 80
  • 101
2

Struts has something like this built in if you happen to be using it.

http://struts.apache.org/1.x/apidocs/org/apache/struts/util/TokenProcessor.html

Konrad
  • 3,593
  • 3
  • 19
  • 17
-2

I'd use a timestamp and compare values with your server side code. If two timestamps are close enough and have the same IP address, ignore the second form submission.

VirtuosiMedia
  • 52,016
  • 21
  • 93
  • 140