RE: Form Double Submit Detection
Tom, You can also put JavaScript code in the form's onSubmit event code to disable all the elements in the form. To make sure this happens after submission (otherwise nothing gets submitted) use window.setTimeout() to run the disable script after a short delay. Another alternative is to put a unique token in a hidden field. The server keeps track of these tokens: once one is spent by submitting the form it can't be reused. This is more bulletproof but needs more coding (though I expect you could use a filter to localize it). Chris -Original Message- From: Bill Lunnon [mailto:[EMAIL PROTECTED] Sent: 27 October 2003 23:26 To: Tomcat Users List Subject: RE: Form Double Submit Detection Tom, Don't know if this is complimentary to your workflow, try a javascript confirm (ie a client side pop-up, asking the user to click Ok to continue). This will catch any double clicks on the client side. Hope this helps Bill -Original Message- From: Tom Parker [mailto:[EMAIL PROTECTED] Sent: Tuesday, 28 October 2003 10:18 AM To: [EMAIL PROTECTED] Subject: Form Double Submit Detection I've designed my workflows so that they do not need to store anything in the user's session. This allows the user to conduct more than one instance of a particular task at the same time without data getting mixed up. However this presents me with a problem if the user double clicks the submit button and causes the server to do something twice. The normal(?) way of detecting this would be to store a unique token in the session and in the form, and compare them to ensure that the user has not submitted this form twice. For this to work, you need to store something in the session for each possible form submission. If the user never submits the form, then the token will hang around for the life of the session as we don't know that the user won't submit the form someday. Currently I'm thinking of allowing the user to store a finite number of duplicate check tokens, or to make the tokens expire after an amount of time. The former doesn't seem very attractive (load a record, view a bunch of other records such that the first record's token is dropped, save the first record - no token found), while the latter could lead to rather a lot of tokens being stored. Is there a solution to this problem that I'm missing? - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] The information in this e:mail and any attachments or any reproduction of this e:mail in whatever manner is confidential and for the use of the addressee(s) only. If you are not the addressee then the distribution, use or reproduction of this e:mail or the information within it is strictly prohibited and may be unlawful. If received in error please advise the sender and delete all record of it from your system. Although believed to be virus free, accurate and complete, responsibility for any loss or cost arising from its receipt or use or its incomplete or inaccurate transmission is hereby excluded to the fullest extent possible. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Form Double Submit Detection
On 10/28/2003 10:42 AM Walker Chris wrote: Tom, You can also put JavaScript code in the form's onSubmit event code to disable all the elements in the form. To make sure this happens after submission (otherwise nothing gets submitted) use window.setTimeout() to run the disable script after a short delay. Another alternative is to put a unique token in a hidden field. The server keeps track of these tokens: once one is spent by submitting the form it can't be reused. This is more bulletproof but needs more coding (though I expect you could use a filter to localize it). jakarta struts has some good token creation code in their TokenProcessor class. Struts uses it so: on requesting the form, struts creates the token, stores it in a hidden field in the form and in the session. On submit, it checks the value of the hidden field against the value in the session. If they are not the same or are missing, it means the token in the form is invalid. I suped up this mechanism to overcome the problem that users opening multiple windows would invalidate the tokens in the all but the most recently opened windows. I don't store the token in the session. When the form submits, I check the session for a hashmap, if the token is not in the hashmap, I allow the transaction and then put the token in the hashmap. Adam -- struts 1.1 + tomcat 5.0.12 + java 1.4.2 Linux 2.4.20 RH9 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Form Double Submit Detection
Justin, Agreed. One word of caution... We actually synchronized on the session... You aren't guaranteed to have the same HttpSession object for every request -- HttpSession is an interface which is implemented internally and wrapped by a facade. Synchronizing on the actual object you get from req.getSession() can potentially leave you synchronizing on totally different objects. Oh, hey. I never really thought of that, although I kinda knew it without ever giving it much thought. Does that mean that you can never have exclusive access to your own session? Since the VM is allowed to play memory tricks when it thinks threads aren't related (which you can only do using memory barriers via synchronization), you can never be sure that the 'session' you're working with is in a consistent state or even valid. That's kinda scary. I'm guessing that in practical terms, there's rarely any reason to think that they're not predictable... -chris - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Form Double Submit Detection
Yes you can, but the only safe way is to synchronize on an object inside the session, not the session itself. Or to synchronize on a more global object (but this is not recommended as this might not scale well for sites with many users) -Original Message- From: Christopher Schultz [mailto:[EMAIL PROTECTED] Sent: Tuesday, October 28, 2003 11:56 AM To: Tomcat Users List Subject: Re: Form Double Submit Detection without ever giving it much thought. Does that mean that you can never have exclusive access to your own session? - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Form Double Submit Detection
On Tue, 2003-10-28 at 23:40, Adam Hardy wrote: I don't store the token in the session. When the form submits, I check the session for a hashmap, if the token is not in the hashmap, I allow the transaction and then put the token in the hashmap. Interesting. You store the successful tokens so they can't be used again, and ignore the tokens that are never returned to the server. This would be more efficient for the case where the user views but never submits more forms than they view and do submit. I'll have to analyse my traffic some time and see what my users are doing. Currently I've implemented the opposite, I keep track of all the tokens and drop those that the user returns. I also drop all tokens older than 2 hours (which means the user has 2 hours to submit any particular form before the token goes away and they can't). (and obviously I store them in the session so they all go away when the session does) I like your solution better than mine. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Form Double Submit Detection
Tom, Don't know if this is complimentary to your workflow, try a javascript confirm (ie a client side pop-up, asking the user to click Ok to continue). This will catch any double clicks on the client side. Hope this helps Bill -Original Message- From: Tom Parker [mailto:[EMAIL PROTECTED] Sent: Tuesday, 28 October 2003 10:18 AM To: [EMAIL PROTECTED] Subject: Form Double Submit Detection I've designed my workflows so that they do not need to store anything in the user's session. This allows the user to conduct more than one instance of a particular task at the same time without data getting mixed up. However this presents me with a problem if the user double clicks the submit button and causes the server to do something twice. The normal(?) way of detecting this would be to store a unique token in the session and in the form, and compare them to ensure that the user has not submitted this form twice. For this to work, you need to store something in the session for each possible form submission. If the user never submits the form, then the token will hang around for the life of the session as we don't know that the user won't submit the form someday. Currently I'm thinking of allowing the user to store a finite number of duplicate check tokens, or to make the tokens expire after an amount of time. The former doesn't seem very attractive (load a record, view a bunch of other records such that the first record's token is dropped, save the first record - no token found), while the latter could lead to rather a lot of tokens being stored. Is there a solution to this problem that I'm missing? - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Form Double Submit Detection
On Tue, 2003-10-28 at 12:26, Bill Lunnon wrote: Don't know if this is complimentary to your workflow, try a javascript confirm (ie a client side pop-up, asking the user to click Ok to continue). This will catch any double clicks on the client side. Unfortunatly I think our users would object to this solution. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Form Double Submit Detection
At 03:34 PM 10/27/2003, you wrote: On Tue, 2003-10-28 at 12:26, Bill Lunnon wrote: Don't know if this is complimentary to your workflow, try a javascript confirm (ie a client side pop-up, asking the user to click Ok to continue). This will catch any double clicks on the client side. Unfortunatly I think our users would object to this solution. On the client side, how about writing a doOnSubmit() javascript function that increments a counter for the number of times it's been called. If the function hasn't submitted the form (counter=0), submit it. If the counter0, notify user of double submission. Of course, if a user has multiple clients open with the same page open, this is no good (and you'd have to keep track on the server). Server side, instead of putting a token in the session when the page is *served*, put a token in the session while the submission is being processed (use it like a semaphore). The token has a finite lifecycle (created on form submission, death on submission response served). There's no need to match tokens unless you're worried about something other than duplicate submission detection (such as security or time-based form relevance). justin - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Form Double Submit Detection
On Tue, 2003-10-28 at 12:51, Justin Ruthenbeck wrote: Server side, instead of putting a token in the session when the page is *served*, put a token in the session while the submission is being processed (use it like a semaphore). The token has a finite lifecycle (created on form submission, death on submission response served). This only works if processing the two submissions overlaps. If the logic to process the submission is very fast, or there is a long delay between submissions, then this won't work. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Form Double Submit Detection
At 04:20 PM 10/27/2003, you wrote: On Tue, 2003-10-28 at 12:51, Justin Ruthenbeck wrote: Server side, instead of putting a token in the session when the page is *served*, put a token in the session while the submission is being processed (use it like a semaphore). The token has a finite lifecycle (created on form submission, death on submission response served). This only works if processing the two submissions overlaps. If the logic to process the submission is very fast, or there is a long delay between submissions, then this won't work. from original post I've designed my workflows so that they do not need to store anything in the user's session. This allows the user to conduct more than one instance of a particular task at the same time without data getting mixed up. However this presents me with a problem if the user double clicks the submit button and causes the server to do something twice. /from original post If the logic to process the submission is very fast, then presumably your client would have a response before clicking the submit button again. If there is a long delay between submissions, then you're dealing with an entirely different problem -- ie not user double clicks the submit button. If you're truly worried about multiple submissions over long periods of time, then it sounds like your system is more transactional in nature. That is, the system generates an eligible transaction on one call (form request), then executes that transaction on another (form submit). In this case, controlling the execution of code should be done on the transaction object level (not request level). justin - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Form Double Submit Detection
On Tue, 2003-10-28 at 14:18, Justin Ruthenbeck wrote: At 04:20 PM 10/27/2003, you wrote: On Tue, 2003-10-28 at 12:51, Justin Ruthenbeck wrote: Server side, instead of putting a token in the session when the page is *served*, put a token in the session while the submission is being processed (use it like a semaphore). The token has a finite lifecycle (created on form submission, death on submission response served). This only works if processing the two submissions overlaps. If the logic to process the submission is very fast, or there is a long delay between submissions, then this won't work. from original post I've designed my workflows so that they do not need to store anything in the user's session. This allows the user to conduct more than one instance of a particular task at the same time without data getting mixed up. However this presents me with a problem if the user double clicks the submit button and causes the server to do something twice. /from original post If the logic to process the submission is very fast, then presumably your client would have a response before clicking the submit button again. If there is a long delay between submissions, then you're dealing with an entirely different problem -- ie not user double clicks the submit button. While the logic on the server is reasonably fast, we can't be sure that the network latency is so low that the user can't double click, nor that the server will always be fast all the time. In fact we have several cases of this actually happening and two records being created on the server. If you're truly worried about multiple submissions over long periods of time, then it sounds like your system is more transactional in nature. That is, the system generates an eligible transaction on one call (form request), then executes that transaction on another (form submit). In this case, controlling the execution of code should be done on the transaction object level (not request level). We do have concurrent update checking which catches this problem in most cases. However that solution does not work when creating a brand new record. From the server point of view it appears to be two requests to create a record, which just happen to have the same details (and in this case we don't want to prevent the user creating apparently duplicate records, so that isn't a solution). - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Form Double Submit Detection
Tom, Don't know if this is complimentary to your workflow, try a javascript confirm (ie a client side pop-up, asking the user to click Ok to continue). This will catch any double clicks on the client side. Unfortunatly I think our users would object to this solution. Server side, instead of putting a token in the session when the page is *served*, put a token in the session while the submission is being processed (use it like a semaphore). The token has a finite lifecycle (created on form submission, death on submission response served). There's no need to match tokens unless you're worried about something other than duplicate submission detection (such as security or time-based form relevance). I've had to do this before when credit card processing was being done. A double-click can result in the credit card being charged twice, so you've really got to avoid it. We actually synchronized on the session for the duration of the processing, and then set a flag in the session once the processing was done. Any subsequent attempts would be flagged as duplicates and you'd just get a results screen. The same could be done for multiple transactions if, as Justin suggests, you put a token into the session *during processing*. Just generate the token when you serve the page and submit it along with the form to be processed. Synchronize on the session to check it and then put the token into the session. If the token is already there, then skip the transaction. It's nice to show a result screen even for a double-submission, so you might want to synchronize on the token itself after you have obtained it from the (synchronized) session. That will allow you to finish the processing from the *first* submission, and then show the results in the second submission. The browser, having submitted twice, will hang up on the first connection and the second one will show the results. You'll have to put the results in the session, then, to display them to the browser for the second submission. It's pretty hairy, no doubt. -chris - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Form Double Submit Detection
At 06:02 PM 10/27/2003, you wrote: On Tue, 2003-10-28 at 14:18, Justin Ruthenbeck wrote: At 04:20 PM 10/27/2003, you wrote: On Tue, 2003-10-28 at 12:51, Justin Ruthenbeck wrote: Server side, instead of putting a token in the session when the page is *served*, put a token in the session while the submission is being processed (use it like a semaphore). The token has a finite lifecycle (created on form submission, death on submission response served). This only works if processing the two submissions overlaps. If the logic to process the submission is very fast, or there is a long delay between submissions, then this won't work. from original post I've designed my workflows so that they do not need to store anything in the user's session. This allows the user to conduct more than one instance of a particular task at the same time without data getting mixed up. However this presents me with a problem if the user double clicks the submit button and causes the server to do something twice. /from original post If the logic to process the submission is very fast, then presumably your client would have a response before clicking the submit button again. If there is a long delay between submissions, then you're dealing with an entirely different problem -- ie not user double clicks the submit button. While the logic on the server is reasonably fast, we can't be sure that the network latency is so low that the user can't double click, nor that the server will always be fast all the time. In fact we have several cases of this actually happening and two records being created on the server. Alright, we're starting to go around in circles. Here's the situation (correct me if I'm wrong): + User fills out a form and clicks submit + The browser submits the form and sits in a wait state + The server begins processing a request for a new record + The user clicks submit once again + The browser submits the form and sits in a wait state again + The server begins processing a second (identical) request This is classic double submission where two requests for the same thing overlap on the server. Your server thinks they are independent, but you only want one to complete since it's actually a user error. In this situation, either of the original 2 suggestions (client or server side) should work. Add client side js code that only allows the user to click a button once. To back it up (don't rely on the client to behave), only allow one submission of that particular form at a time. Make sure the form does not get cached. The only way a client will get around this is to have two separate copies of the form and submit both of them -- presumably this would mean they *intend* to have two copies. This takes care of accidental double clicking. If you absolutely must guarantee that the form is only submitted once, then you have no choice but to create a UID for the form and match it before allowing the submission, in one way or another. And if you're concerned about this affecting your long term memory performance, there are ways to mitigate the impact ... you almost surely don't need this level of guantees for every request. Let me know if I'm not understanding what you're trying to get at ... doesn't sound like your requirements are any different than general double-click defenses, though. Cheers, justin - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Form Double Submit Detection
Agreed. One word of caution... At 06:46 PM 10/27/2003, you wrote: I've had to do this before when credit card processing was being done. A double-click can result in the credit card being charged twice, so you've really got to avoid it. We actually synchronized on the session for the duration of the processing, and then set a flag in the session once the processing was done. Any subsequent attempts would be flagged as duplicates and you'd just get a results screen. You aren't guaranteed to have the same HttpSession object for every request -- HttpSession is an interface which is implemented internally and wrapped by a facade. Synchronizing on the actual object you get from req.getSession() can potentially leave you synchronizing on totally different objects. justin - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Form Double Submit Detection
On Tue, 2003-10-28 at 15:49, Justin Ruthenbeck wrote: Here's the situation (correct me if I'm wrong): + User fills out a form and clicks submit + The browser submits the form and sits in a wait state + The server begins processing a request for a new record + The user clicks submit once again + The browser submits the form and sits in a wait state again + The server begins processing a second (identical) request This is classic double submission where two requests for the same thing overlap on the server. Your server thinks they are independent, but you only want one to complete since it's actually a user error. You understand the situation perfectly. And if you're concerned about this affecting your long term memory performance, there are ways to mitigate the impact ... you almost surely don't need this level of guantees for every request. I did the numbers and found that for our expected workload we couldn't possibly use more than a couple of megs of memory keeping track of a unique token for each form served. I'm dropping them after some time (I haven't decided how long yet, but I think a couple of hours is probably long enough) which should keep the memory usage under control. Thanks everyone for your input. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]