October 23, 2006
Double Submit Protection
The ease with which a user can inadvertently or deliberately submit a web form multiple times is a persistent problem with web applications and web forms.
Typically this problem arises when a user attempts to submit a form and the server does not immediately respond to the request. The delay can be due to network traffic, high load, or a particularly complex action that must be completed. In any event, it does not take long before the user begins to wonder if they actually hit the button and they click it again just to make sure.
If your application is not properly designed, this can lead to multiple identical records, or actions being processed more than once. Sometimes with undesirable side effects (like multiple billing).
There are a couple of solutions to this problem.
- Warn the user to avoid clicking the button more than once…. this is a complete cop out on the part of the programmers and is just inviting trouble.
- Disable the submit button when pressed (using AJAX). This sort of works, but if the server is slow and non-responsive, this is likely to fail too. This will also fail if the user has JS turned off, or if they reload or go back to the form and resubmit.
- Disable the button via javascript. This works reasonably well, but if the user uses the browser back button, they can press the submit button again, resulting in a double submit. Again, this will fail if JS is turned off
The reality is that all of these solutions have problems and don’t really address the underlying issue. The real problem is not that the user is submitting multiple copies of the same request, the problem is that the server is trying to act on all of them.
The double_submit_protection plugin for Rails
How it works.
- User submits a request
- If the request is successfully processed, it records the time and the contents of the params
- if a request with an identical params array is processed within a predefined interval it will reject the request or redirect to another page
The user can then do whatever they want and they won’t be able to send the identical request again until the time interval expires.
If they change the content of the form and resubmit, that request will work.
Installation
Usage:
First, restart your server.
To protect your entire application from duplicate post requests (non-ajax) you can put the following code in your application controller.
-
## application.rb
-
-
double_submit_protection :method=>:post,
-
:xhr => false,
-
:interval => 60,
-
:flash => {:warning => ‘Double Submit Detected’},
-
:redirect_to => {:action=>’index’}
Disclaimer and Tips
This is beta stuff, so don’t be surprised if it breaks things. In particular, it can block some repeated AJAX calls if you don’t configure it properly.
Note that since it uses a before filter to do it’s dirty work, you can limit the actions it applies to by passing an parameters like
:except=>['action']
You may need to adjust the timeout period to suit your needs. Longer timeouts will make your session object get pretty big.
If you have a datetime_select in your form, it may circumvent any timeout interval. If this control defaults to the current time, then the plugin will not be able to tell that it is the same because the ‘minutes’ field will be changing. It should work fine against multiple submit presses, but it will have a harder time with refresh-submit cases. Future versions may have the option to ignore datetimes in the params.
Filed by Kevin Olbrich at 12:31 am under Ruby on Rails, plugins
11 Comments