Explain Codes LogoExplain Codes Logo

How to prevent form resubmission when page is refreshed (F5 / CTRL+R)

javascript
form-validation
csrf-protection
client-side-validation
Alex KataevbyAlex KataevΒ·Nov 24, 2024
⚑TLDR

The Post/Redirect/Get (PRG) pattern is the go-to approach. After processing form data, a 302 redirection is implemented to a confirmation page or back to the initial form.

For example, in PHP:

if($_SERVER['REQUEST_METHOD'] == 'POST') { // process form, but beware, here be dragons πŸ‰... header('Location: confirmation.php'); // Our escape hatch exit; }

With this, a refresh triggers a GET request to confirmation.php, preventing repeat submissions.

Safeguarding user input data

It's critical to prevent resubmission, but also important to ensure the user doesn't lose their entered data. We can utilize sessions or cookies to hold the user's form data temporarily; this allows us to repopulate the forms upon redirection, ensuring a seamless user experience:

session_start(); // Let's start the party πŸŽ‰ if($_SERVER['REQUEST_METHOD'] == 'POST') { // Stash the loot in the session $_SESSION['form_data'] = $_POST; // Make a swift exit header('Location: ' . $_SERVER['PHP_SELF']); exit; } elseif (!empty($_SESSION['form_data'])) { // Retrieve the stashed loot $form_data = $_SESSION['form_data']; // Clean up after ourselves πŸ’… unset($_SESSION['form_data']); }

In JavaScript, localStorage or sessionStorage offer similar options without server-side manipulation.

Unique identifiers & server-side idempotence

Creating a unique identifier on form submission, either through user sessions or database entries, ensures each form submission is coupled with a unique token. We can validate this token on form submission and invalidate it afterwards to prevent re-entry:

session_start(); // All aboard the session train! πŸš‚ $unique_id = bin2hex(random_bytes(16)); // Securing our Hogwarts acceptance letter $_SESSION['form_unique_id'] = $unique_id; // Stash the letter

In your form handling logic:

if($_SERVER['REQUEST_METHOD'] == 'POST') { if($_POST['form_unique_id'] === $_SESSION['form_unique_id']) { // Verify our owl-delivered letter πŸ¦‰ // proceed with form handling // Obliterate πŸ’₯ the letter after one magical journey unset($_SESSION['form_unique_id']); header('Location: confirmation.php'); exit; } }

Client-side fortifications

Beyond server-side PRG, JavaScript client-side enhancements can also be put to use. The window.history.replaceState is a key tool for manipulating browser history:

if (window.history.replaceState) { window.history.replaceState(null, null, window.location.href); // Let's pull a secret agent move and scrub our tracks πŸ•΅οΈβ€β™‚οΈ }

This technique removes form data from the browser's refresh action, redirecting to the same page sans the data, thus preventing resubmission.

Security practices

Maintain data integrity and protect your forms against Cross-Site Request Forgery (CSRF). Employ tokens and hashing algorithms to generate secure tokens. Validation checks during form processing further ensure safety.

Solver of the user experience puzzle

All applied techniques should be seamless, causing no user inconvenience. Validate inputs on the client-side first to prevent unnecessary server-side processing and potential resubmission pitfalls.

Test before you rest

Review your form submission processes regularly and conduct penetration tests. The server logic and client-side validation should work together to reliably prevent form resubmission.