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

后端 未结 23 1283
醉话见心
醉话见心 2020-11-22 00:46

I have a simple form that submits text to my SQL table. The problem is that after the user submits the text, they can refresh the page and the data gets submitted again with

相关标签:
23条回答
  • 2020-11-22 01:26

    A pretty surefire way is to implement a unique ID into the post and cache it in the

    <input type='hidden' name='post_id' value='".createPassword(64)."'>
    

    Then in your code do this:

    if( ($_SESSION['post_id'] != $_POST['post_id']) )
    {
        $_SESSION['post_id'] = $_POST['post_id'];
        //do post stuff
    } else {
        //normal display
    }
    
    function createPassword($length)
    {
        $chars = "abcdefghijkmnopqrstuvwxyz023456789";
        srand((double)microtime()*1000000);
        $i = 0;
        $pass = '' ;
    
        while ($i <= ($length - 1)) {
            $num = rand() % 33;
            $tmp = substr($chars, $num, 1);
            $pass = $pass . $tmp;
            $i++;
        }
        return $pass;
    }
    
    0 讨论(0)
  • 2020-11-22 01:27

    A refined version of Moob's post. Create a hash of the POST, save it as a session cookie, and compare hashes every session.

    // Optionally Disable browser caching on "Back"
    header( 'Cache-Control: no-store, no-cache, must-revalidate' );
    header( 'Expires: Sun, 1 Jan 2000 12:00:00 GMT' );
    header( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT' );
    
    $post_hash = md5( json_encode( $_POST ) );
    
    if( session_start() )
    {
        $post_resubmitted = isset( $_SESSION[ 'post_hash' ] ) && $_SESSION[ 'post_hash' ] == $post_hash;
        $_SESSION[ 'post_hash' ] = $post_hash;
        session_write_close();
    }
    else
    {
        $post_resubmitted = false;
    }
    
    if ( $post_resubmitted ) {
      // POST was resubmitted
    }
    else
    {
      // POST was submitted normally
    }
    
    0 讨论(0)
  • 2020-11-22 01:28

    Use the Post/Redirect/Get pattern. http://en.wikipedia.org/wiki/Post/Redirect/Get

    With my website, I will store a message in a cookie or session, redirect after the post, read the cookie/session, and then clear the value of that session or cookie variable.

    0 讨论(0)
  • 2020-11-22 01:29

    I searched for solution to prevent resubmission in a huge project afterwards. The code highly works with $_GET and $_POST and I can't change the form elements behaviour without the risk of unforeseen bugs. So, here is my code:

    <!-- language: lang-php -->
    <?php
    
    // Very top of your code:
    
    // Start session:
    session_start();
    
    // If Post Form Data send and no File Upload
    if ( empty( $_FILES ) && ! empty( $_POST ) ) {
        // Store Post Form Data in Session Variable
        $_SESSION["POST"] = $_POST;
        // Reload Page if there were no outputs
        if ( ! headers_sent() ) {
            // Build URL to reload with GET Parameters
            // Change https to http if your site has no ssl
            $location = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
            // Reload Page
            header( "location: " . $location, true, 303 );
            // Stop any further progress
            die();
        }
    }
    
    // Rebuilt POST Form Data from Session Variable
    if ( isset( $_SESSION["POST"] ) ) {
        $_POST = $_SESSION["POST"];
        // Tell PHP that POST is sent
        $_SERVER['REQUEST_METHOD'] = 'POST';
    }
    
    // Your code:
    ?><html>
        <head>
            <title>GET/POST Resubmit</title>
        </head>
        <body>
    
        <h1>Forms:</h1>
        <h2>GET Form:</h2>
        <form action="index.php" method="get">
            <input type="text" id="text_get" value="test text get" name="text_get"/>
            <input type="submit" value="submit">
        </form>
        <h2>POST Form:</h2>
        <form action="index.php" method="post">
            <input type="text" id="text_post" value="test text post" name="text_post"/>
            <input type="submit" value="submit">
        </form>
        <h2>POST Form with GET action:</h2>
        <form action="index.php?text_get2=getwithpost" method="post">
            <input type="text" id="text_post2" value="test text get post" name="text_post2"/>
            <input type="submit" value="submit">
        </form>
        <h2>File Upload Form:</h2>
        <form action="index.php" method="post" enctype="multipart/form-data">
            <input type="file" id="file" name="file">
            <input type="submit" value="submit">
        </form>
    
        <h1>Results:</h1>
        <h2>GET Form Result:</h2>
        <p>text_get: <?php echo $_GET["text_get"]; ?></p>
        <h2>POST Form Result:</h2>
        <p>text_post: <?php echo $_POST["text_post"]; ?></p>
        <h2>POST Form with GET Result:</h2>
        <p>text_get2: <?php echo $_GET["text_get2"]; ?></p>
        <p>text_post2: <?php echo $_POST["text_post2"]; ?></p>
        <h2>File Upload:</h2>
        <p>file:
        <pre><?php if ( ! empty( $_FILES ) ) {
                echo print_r( $_FILES, true );
            } ?></pre>
        </p>
        <p></p>
        </body>
        </html><?php
    // Very Bottom of your code:
    // Kill Post Form Data Session Variable, so User can reload the Page without sending post data twice
    unset( $_SESSION["POST"] );
    

    It only works to avoid the resubmit of $_POST, not $_GET. But this is the behaviour I need. The resubmit issue doesn't work with file uploads!

    0 讨论(0)
  • 2020-11-22 01:30

    This form.php sample shows how to use PRG correct (when form is valid or not).

    • It redirects to the same page, only when form is valid and action was performed.
    • Redirection protects form from being resubmitted on page refresh.
    • It uses session to not loose success messages you want to show when form is valid.
    • There are two buttons for testing: "Valid submit", "Invalid submit". Try both and refresh page after that.
    <?php
    session_start();
    
    function doSelfRedirect()
    {
      header('Location:'.$_SERVER['PHP_SELF']);
      exit;
    }
    
    function setFlashMessage($msg)
    {
      $_SESSION['message'] = $msg;
    }
    
    function getFlashMessage()
    {
      if (!empty($_SESSION['message'])) {
        $msg = $_SESSION['message'];
        unset($_SESSION['message']);
      } else {
        $msg = null;
      }
    
      return $msg;
    }
    
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
      // Validation primitive example.
      if (empty($_POST['valid'])) {
        $formIsValid = false;
        setFlashMessage('Invalid form submit');
      } else {
        $formIsValid = true;
      }
    
      if ($formIsValid) {
        // Perform any actions here.
        // ...
    
        // Cool!
        setFlashMessage('Form is valid. Action performed.');
    
        // Prevent form resubmission.
        doSelfRedirect();
      }
    }
    ?>
    <h1>Hello form</h1>
    
    <?php if ($msg = getFlashMessage()): ?>
      <div><?= $msg ?></div>
    <?php endif; ?>
    
    <form method="post">
      <input type="text" name="foo" value="bar"><br><br>
      <button type="submit" name="invalid" value="0">Invalid submit</button>
      <button type="submit" name="valid" value="1">Valid submit</button>
    </form>
    
    0 讨论(0)
  • 2020-11-22 01:32

    Javascript

    This method is quite easy and blocks the pop up asking for form resubmission on refresh once the form is submitted. Just place this line of javascript code at the footer of your file and see the magic.

    <script>
        if ( window.history.replaceState ) {
            window.history.replaceState( null, null, window.location.href );
        }
    </script>
    
    0 讨论(0)
提交回复
热议问题