The question you'll have to ask yourself first is: What is the kind of problem scenario you want to avoid?
- The user accidentally (or out of frustration, ...) clicking a button twice.
- 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.