phppost-redirect-get

what is a good way to display form data on last page using PRG pattern


I would like to use the PRG pattern to prevent form-resubmission, because the submission involves sending a mail. The problem with this approach though, is that I don't seem to find the "right" way to show the user what data has been sent after the redirect. Currently I am doing something like:

Some page with the form (index.html)

<form action="handleform.php" method="post">
    <input type="text" name="name" placeholder="Name" required />
    <input type="text" name="tel" placeholder="Telephone" />
    <input type="email" name="mail" placeholder="E&#8209;Mail" required />

    <!-- and more input fields -->
</form>

Some script handleform.php that handles the form data

<?php
    $data[0] = filter_var(INPUT_POST, "name", FILTER_SANITIZE_FULL_SPECIAL_CHARS);
    $data[1] = filter_var(INPUT_POST, "tel", FILTER_SANITIZE_NUMBER_INT);
    $data[2] = filter_var(INPUT_POST, "mail", FILTER_VALIDATE_EMAIL);

    // process rest of data and create mail

    $mail->Body = getNiceHTML($data);

    $mail->send();
    header("Location: formhandled.php?id=" . urlencode($mail->Body));
    exit();
?>

and a scripted page formhandled.php to display upon success

<!-- header and menu html -->

<?php
    echo $_GET["id"];
?>

<!-- footer html -->

The problem with this approach is that I got the idea that this exposes all the entered data in the URL and thus might be too vulnerable. On top of that, the HTML-string makes the URL rather lengthy. I could think of two other approaches to solve my problem

  1. Store the string in a (temporary) file and pass the filename, but then I would need to find some way to delete these files after I left the formhandled.php in order to prevent that this information stays on the server longer than necessary.
  2. Start a session. The main problem with this approach is that I could only display the data if the user did not disable cookies (if I understood that correctly).

but I don't see why these would be better/worse. I also can't imagine that no-one ever did something like this, but I couldn't find anything on how this problem is solved.

Therefore my question: how to display the entered form data after redirecting?


Solution

  • There are two ways to transport that data:

    1. Transport it client side, which in the case of a redirect means through the URL or possibly cookies.
    2. Transport it server side, meaning the server stores the data and retrieves it again on the next page.

    You've pretty much got that already. Transporting it client-side is indeed a bit yucky here; you don't really want to put all this information into the URL (not because of "vulnerabilities", there aren't many concerns with just printing data from the URL to the screen), and you'd want to avoid setting cookies just for this.

    The best solution it pretty much:

    1. the server stores the data in a short-term auto-purging location with a unique id
    2. you send the unique id through the URL as query parameter
    3. you retrieve the data from the short-term location with the id, display it, then discard it

    Now, what would qualify as a good short-term storage for this? Sessions would be good, and you could transport the session id through the URL instead of cookies. This is probably the easiest solution with built-in PHP tools. Alternatively something like a Redis store or similar in-memory store would be very useful to have for cases like this; but may be overkill to set up just for this purpose alone. If you're already running a database, you could store the data there.

    Whichever solution you choose, you must ensure that the data will be automatically discarded sooner or later. If for whatever reason the user does not visit the redirect page, the temporarily stored data will pile up on your server, which you want to avoid. Sessions auto-garbage collect, Redis data can be purged automatically, and with a database you can run an occasional cleanup query via various mechanisms.