Php – How to prevent multiple form submissions when user reloads the page

apidesign-patternslaravelPHPsoap

I'm currently working on a project which requires that we integration a 3rd party SOAP API to handle a number of basic CRUD type operations.

Our current implementation allows us to leveraging the Laravel framework's form validation classes prior to execution of these API requests data; however I have some concerns since we're not leveraging any type of queuing mechanism.

The current solutions stack involves placing a heavy burden on the NGINX web server to spawn additional workers for each blocking user request. Obviously, this may lead to some issues down the line in terms of scalability.

There's also the possibility that users will frequently "refresh" pages after submitting form request data.

I've been looking into the Post/Redirect/Get pattern as a possible solution however I'm not quite sure that I completely understand the concept.

Here's a quote from one stackoverflow discussion:

  1. The client gets a page with a form.

  2. The form POSTs to the server.

  3. The server performs the action, and then redirects to another page.

  4. The client follows the redirect.

As stated above, these are long API calls and step 3 may take upwards of 10s to complete execution- what's to prevent the user from continually refreshing the page after step 2?

Best Answer

I have answered this question on StackOverflow as well - I place my answer here for easy reference...

The PRG pattern alone will not prevent this, as the P action in it takes time (which is usually the case) and the user can submit the form again (via click or browser refresh), which will cause the PRG pattern to "fail".

Note that malicious users can also bypass all of your client side measures by running multiple http posts in quick succession.

A solution to all of the above is to check for duplicate submissions on server side against your anti-forgery token.

If you make use of a hidden anti-forgery token in your form (as you should), you can cache the anti-forgery token on first submit and remove the token from cache if required, or expire the cached entry after set amount of time.

You will then be able to check with each request against the cache whether the specific form has been submitted and reject it if it has.

Related Topic