Solving the Double Submission Issue
I would like to see how Web Developers avoid the double submission problem. So basically my understanding of the problem is as follows:
Double submission occurs when a开发者_StackOverflow社区n impatient user submits a form multiple times, causing issues. This problem can be fixed by JavaScript (specifically jQuery scripts) that disable the submit button once the form has been submitted - a weakness of this is if clients have JavaScript disabled.
There is also server side methods of detection.
So my questions are:
How do people overcome double submission? What is a real life example of a problem caused by double submits? Do any Web Application Frameworks have double submission tools built in?
Real life situation: placing bets on a betting website. Users would double click and get two bets placed. Not good! Javascript checks were not sufficient to prevent this.
Solution:
Create UUID/GUID hidden input in form using server-side scripting language that renders the form.
On form submission immediately add this to a database table called
UniqueSubmissions
(for example). Then proceed with processing.Every subsequent request with the same UUID/GUID will be rejected if found in the
UniqueSubmissions
table.
This worked for us. Hope that helps answer your question!
If you are working with java server side scripting and also using struts 2 then you refer this link which talks about on using token .
http://www.xinotes.org/notes/note/369/
A token should be generated and kept in session for the initial page render, when the request is submitted along with the token for the first time , in struts action run a thread with thread name as the token id and run the logic whatever the client has requested for , when client submit again the same request, check whether the thread is still running(thread.getcurrentthread().interrupted) if still running then send a client redirect 503.
Please look at the ExecuteAndWaitInterceptor of struts 2code, the logic of this combined with token will help out fast click
Use the redirect-after-post or sometimes called PRG (post/redirect/get)
In short, when the user posts the form, you perform a client side redirect (after consuming the post data) to the response (success) page.
A real life example would be this answer posted twice ;-). If you don't want to rely on any aspect of the client side (javascript, or even cookies), you can calculate an MD5 hash of the data submitted, possibly by adding information such as source IP and the browser used, and reject posts that have the same hash.
The web2py framework has built-in protection against double form submission. It stores a one-time token in the session as well as in a hidden field in the form, and they must match upon submission or the submission is rejected. This method also protects against CSRF (cross-site request forgery).
If the form has an intention of providing an interface for saving some data in server dbms, you may use special revision field that is mandatory for submitted data. A check whether or not the submitted revision matches that of the latest version of the data in the database (or is that of a new piece of data to be inserted), could provide you with good control of what to do if several submits are made in sequence.
Using struts web-application framework we can handle this problem as follows:
Struts has 3 methods use for the token, saveToken(), isTokenValid() and resetToken()
.
saveToken()
- generate the token key and save to request/session attribute.
isTokenValid()
- validate submitted token key against the 1 store in request/session.
resetToken()
- reset the token key.
How it works:
1) Upon loading the form, invokes saveToken()
on the action class to create and store the token key. Struts will store the generated key in request/session. If the token successfully created, when view source on the browser you will see something similar to the following, the token key is stored as a hidden field:
<form action="myaction.do" method="post">
<input type="hidden"
name="<%= Constants.TOKEN_KEY %>"
value="<%= session.getAttribute(Action.TRANSACTION_TOKEN_KEY) %>" >
2) Once the form submitted, invokes isTokenValid()
on the action class, it will validate the submitted token key(hidden field) with the token key stored previously on request/session. If match, it will return true.
public final ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
saveToken(request);
if (!tokenIsValid(request)) {
//forward to error page saying "your transaction is already being processed"
} else {
//process action
//forward to jsp
}
// Reset token after transaction success.
resetToken(request);
}
reference
精彩评论