3

I am building an GWT application with lot's of forms. I am using gwt-platform with its dispatch module.

The next step in my mind is to prevent double-submits ON SERVER SIDE. The problem is that I don't know how to do it exactly...

I thought of something like this:

  1. When application loads the server gives some generated token to the client
  2. The server stores the token inside HTTPSession
  3. When the client submits a form it will send the token from (1.) along with the form
  4. The server checks if the sent token == token inside HTTPSession
  5. In the answer to the client it will send a new token

Is it safe to store the token inside HTTPSession? Or should I simply create a HashMap on the server that maps from SESSION_ID to generated token?

Or maybe there is already an implementation of that in GWT or gwt-platform or somewhere else?

Thanks

Benjamin M
  • 23,599
  • 32
  • 121
  • 201

1 Answers1

5

The question you'll have to ask yourself first is: What is the kind of problem scenario you want to avoid?

  1. The user accidentally (or out of frustration, ...) clicking a button twice.
  2. A resource that is available only once (like a reservation for a certain seat in an airplane) being consumed twice.

Don't just say "I want to avoid both". Even if you do, you'll have to deal with the two problems separately.

Problem 1

This is better solved on the client side (e.g. by disabling the button once it is clicked).

It can also be solved on the server side (by checking sequence numbers or tokens or maybe the hash code of the contents, ...), but I don't really see the point. If the user really wants to submit twice (e.g. by manipulating the JavaScript such that the button doesn't get disabled), then just let them: Problem 1 is not about security.

Problem 2

This must (except in very specific situations) be solved on the server side. It's chiefly about security. But when you think about it, this problem can't be solved by double-submit prevention! Why not?

Let's look at our example: A seat in an airplane must be reserved only once. This can be violated in multiple ways:

  • By double-submit.
  • By the same user submitting at the same time e.g. from different browser windows.
  • By mutliple users trying to reserve at the same time.

The clean way to solve the problem is to check for availability of the seat atomically with reserving the seat. It doesn't really matter, if a violation was caused by double-submit (accidental double-submits are covered by problem 1).

... and Problem 3

If you have implemented some auto-resubmit mechanism, then you might also encounter a third kind of problem:

Let's say the user wants to add an item to his shopping cart. The client submits, and doesn't receive a response from the server before time-out. So it sends again automatically. The server however receives both messages, and tries to process them both - so it adds the item twice to the shopping cart.

The best solution to avoid this in my opinion is generally not to use actions like "add one item to the cart", but "set the target count of items to 1". Again, you could also work with sequence numbers etc.

Chris Lercher
  • 37,264
  • 20
  • 99
  • 131
  • Thank you for your answer. Problem 1 is pretty easy and straight forward. I want to prevent malicious users that, for example, try to flood my database with lot's of entries. Those guys use firebug or whatever and modify the original JavaScript code. So the idea was that every form-submit needs a token which the server can check. – Benjamin M May 22 '12 at 01:17
  • @Benjamin: I see your point - and yes, it's possible to work with tokens, and store them e.g. in the HTTPSession (I wouldn't store passwords there, because the session contents can be written to disk, but as long as you don't build your security around these tokens, this should be safe enough). However, I don't know if this will really stop the bad guys from flooding your DB: They can simply ask the server for more tokens. In the end, this is just rate-limiting, but you could achieve this more easily by directly rate-limiting the save actions per user. – Chris Lercher May 22 '12 at 05:21
  • Thanks :) With "per user" you mean IP or SESSION_ID? Because at the moment there will be some forms where users can submit without being logged in. I have still some questions about the HTTPSession: How does it exactly work? Does the client send the contents of it with every request to the server? – Benjamin M May 22 '12 at 08:56
  • @Benjamin: Well, if the users can submit without logging in, then you'd probably limit by IP - this isn't ideal, but you don't have any real options then. / How HTTPSessions work? You should do a search on the subject, but just quickly: No, they don't send the entire data back and forth, they just send an id (often named JSESSIONID, usually using a cookie), the data is stored on the server (and often survives a server restart, depending on configuration). I strongly recommend using some network tool or plugin (e.g. Firebug) to inspect which data is actually sent over the wire. – Chris Lercher May 22 '12 at 09:55