Avatar billede fredand Forsker
26. april 2012 - 09:59 Der er 8 kommentarer

How to avoid double requests from a form?

Hello guys!

We got an application where we got a bug reported that there seems like the user manage to do som doubleklicking and send a form twice.
(At the server we see in the log that ther has been two identically request at the same time (or almost the same time) before the server has respond to the first.)
The submiting of the form is handled by the follwing javascript.
How ever me my self has not been able to reproduce the twice-submitting.
What do you think guys is this possible that a user can send a form twice before the server has respond to the first.
And do you see some nice way to handle this, perhaps a disable of some button before (or after) the submit.
All suggestions is welcome!

  function checkChoice(button)
  {
      var buttonText = button.value;
      var confText = "";
      if(buttonText == "A")
      {
        confText = "AAA";
      }
      else if(knapptext == "B")
      {
        buttonText = "BBB";
      }
      return confirm(confText);
  }
 
  function sendToServer(button)
  {
        if(checkLength(button.form.friText))
        {
            setButtonText(button);
        }
  }
 
  function checkLength(area)
  {
var text = area.value;
if(text.length > 255)
{
  alert("Maximum length is 255. No you got " + text.length + " chars.");
  return false;
}
return true;
  }
 
  function setButtonText(button)
  {
      button.form.buttonText.value = button.value;
      button.form.submit();
  }
 
 
In the form in the jsp we got;
<html:hidden property="buttonText" value="" />
<textarea name="fritext"></textarea>
<html:button  property="sparaknapp" onclick="if(checkChoice(this)){sendToServer(this);}" value="<%=MyDTO.getButtonText()%>" />
Avatar billede fredand Forsker
26. april 2012 - 11:27 #1
I see some misspelling in my attpemt above to generalize the java script. I seam to have miss some replacing of names of vars.
Hope you understand what I try to convey.
Best regards
Fredrik
Avatar billede arne_v Ekspert
26. april 2012 - 14:00 #2
The Java EE way is to use a "synchronizer token".
Avatar billede fredand Forsker
26. april 2012 - 14:24 #3
Hello Arne!

I guess you mean that it should be handle on the server side?
I googled and found:
http://www.corej2eepatterns.com/Design/PresoDesign.htm
I will start to read about it right at once!

My first idea was to do something like:

  function setButtonText(button)
  {
      button.form.buttonText.value = button.value;

      if(button.disabled == false)
      {
        button.disabled = true;
        button.form.submit();
      }
  }

Unless something else goes wrong in the long chain of calls to this method, all next calls to this method, to the submit-part, should be blocked in my opinion.

Best regards
Fredrik
Avatar billede arne_v Ekspert
27. april 2012 - 03:53 #4
You can do something client side as well, but in general I prefer server side over client side JavaScript.
Avatar billede fredand Forsker
27. april 2012 - 09:50 #5
Hello!

Yes I think you are right, the server side seems to be the best way to solve it.

How ever after some googling it seems like the implementation is something that is subject for debate.
http://www.coderanch.com/t/51602/Struts/Duplicate-form-submission-Synchronizer-Token

What do you think about this approache given that you got these parts and flow:

DisplayAction
form.jsp
SaveAction


1) At DisplayAction, always put a uniqe token in the session like System.currentTimeMillis()

2) At the form.jsp, allways put the token-value into a hidden field

3a) At SaveAction, before the save part, perhaps in validate() check that:
        String tokenSession = (String)request.getSession().getAttribute("token");
        String tokenRequest = request.getParameter("token");
        if( !tokenRequest.equals( tokenSession ))
        {
            //CREATE ERROR MESSAGE       
}
3b) At SaveAction, just after the check remove the token in the save part always remove the token. Then forward to for example DisplayAction again.

If the user in some how double submit the form like server has not respond yet and user clicks browser-back-button and submits the same form again. Then we should be able to indicate a double submit at the server since the same token is sent twice and and should not match the session that now do not got any token. Then server responds with an error-message.

What do you think?

Best regards
Fredrik
Avatar billede arne_v Ekspert
27. april 2012 - 22:17 #6
First question: what server side framework do you use? (Struts, JSF, Spring MVC, Shale, ....)
Avatar billede arne_v Ekspert
28. april 2012 - 02:10 #7
Your flow looks fine.

If you want to be very safe then you should consider race conditions between getting token and removing token.

You can get implementations for many Java web frameworks, which may save you some work.
Avatar billede arne_v Ekspert
28. april 2012 - 02:12 #8
What the server side solution does that client side JS solution disabling the submit button does not are:

1) work if JavaScript is disabled in browser (very rare today)

2) work if the user clicks back and click OK to resubmit without thinking

3) work if the form is submitted with method GET and it is bookmarked and the bookmark is used (very bad to use GET for an update!)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester