wake-up-neo.net

So verhindern Sie die erneute Formularübertragung, wenn die Seite aktualisiert wird (F5/STRG + R)

Ich habe ein einfaches Formular, das Text an meine SQL-Tabelle übermittelt. Das Problem ist, dass der Benutzer, nachdem er den Text übermittelt hat, die Seite aktualisieren kann und die Daten erneut übermittelt werden, ohne das Formular erneut ausfüllen zu müssen. Ich könnte den Benutzer auf eine andere Seite umleiten, nachdem der Text gesendet wurde, aber ich möchte, dass Benutzer auf derselben Seite bleiben.

Ich erinnere mich an etwas gelesen zu haben, in dem ich jedem Benutzer eine eindeutige Sitzungs-ID gab und mit einem anderen Wert vergleicht, der das Problem löste, das ich habe, aber ich habe vergessen, wo es ist.

94
user701510

Verwenden Sie das Post/Redirect/Get-Muster. http://en.wikipedia.org/wiki/Post/Redirect/Get

Mit meiner Website werde ich eine Nachricht in einem Cookie oder einer Sitzung speichern, nach dem Beitrag umleiten, das Cookie/die Sitzung lesen und dann den Wert dieser Sitzung oder Cookie-Variablen löschen.

72
Keverw

Ich möchte auch darauf hinweisen, dass Sie eine Javascript-Methode verwenden können, window.history.replaceState, um das erneute Senden einer Schaltfläche zum Aktualisieren und Zurück zu verhindern.

<script>
    if ( window.history.replaceState ) {
        window.history.replaceState( null, null, window.location.href );
    }
</script>

Konzeptnachweis hier: https://dtbaker.net/files/prevent-post-resubmit.php

Ich würde immer noch einen Post/Redirect/Get-Ansatz empfehlen, aber dies ist eine neuartige JS-Lösung.

38
dtbaker

Sie sollten ein Post-Redirect-Get-Muster verwenden, um dieses Problem zu lösen. Wenn Sie jedoch in einer Position gelandet sind, in der PRG nicht möglich ist (z. B. das Formular selbst ist in einem Include enthalten, um Weiterleitungen zu verhindern), können Sie einige der Anforderungsparameter anhängen Erstellen Sie eine Zeichenfolge basierend auf dem Inhalt und prüfen Sie, ob Sie die Zeichenfolge noch nicht gesendet haben.

//create digest of the form submission:

    $messageIdent = md5($_POST['name'] . $_POST['email'] . $_POST['phone'] . $_POST['comment']);

//and check it against the stored value:

    $sessionMessageIdent = isset($_SESSION['messageIdent'])?$_SESSION['messageIdent']:'';

    if($messageIdent!=$sessionMessageIdent){//if its different:          
        //save the session var:
            $_SESSION['messageIdent'] = $messageIdent;
        //and...
            do_your_thang();
    } else {
        //you've sent this already!
    }
16
Moob

sie können pervent Form Wiedervorlage über Sitzungsvariable Like

zuerst müssen Sie Rand () in der Textbox und $ _SESSION ['Rand'] auf der Formularseite setzen

<form action="" method="post">
  <?php
   $Rand=rand();
   $_SESSION['Rand']=$Rand;
  ?>
 <input type="hidden" value="<?php echo $Rand; ?>" name="randcheck" />
   Your Form's Other Field 
 <input type="submit" name="submitbtn" value="submit" />
</form>

Nach dem Überprüfen von $ _SESSION ['Rand'] mit dem Textfeld $ _POST ['randcheck'] valueLike

         if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['Rand'])
          {
         //Your Code here
         }
12
Savoo

Wenn das Formular verarbeitet wird, leiten Sie auf eine andere Seite um:

... process complete....
header('Location: thankyou.php');

sie können auch auf dieselbe Seite umleiten.

wenn Sie so etwas wie Kommentare machen und möchten, dass der Benutzer auf derselben Seite bleibt, können Sie Ajax verwenden, um die Formularübergabe zu bearbeiten

12
Ibu
  1. Verwenden Sie die Kopfzeile und leiten Sie die Seite um.

    header("Location:your_page.php"); Sie können auf dieselbe Seite oder auf eine andere Seite umleiten.

  2. Deaktivieren Sie $ _POST, nachdem Sie es in die Datenbank eingefügt haben.

    unset($_POST);

11
Prasanth Bendra

Ich verwende diese Javascript-Zeile, um das Popup zu blockieren, das die erneute Vorlage des Formulars beim Aktualisieren fordert, sobald das Formular gesendet wurde. 

if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}

Platzieren Sie diese Zeile einfach in der Fußzeile Ihrer Datei und sehen Sie die Magie

8
Mo'men Mohamed

Ich fand die nächste Problemumgehung. Sie können die Weiterleitung nach der Verarbeitung der POST-Anforderung umgehen, indem Sie history object bearbeiten. 

Sie haben also das HTML-Formular:

<form method=POST action='/process.php'>
 <input type=submit value=OK>
</form>

Wenn Sie dieses Formular auf Ihrem Server verarbeiten, müssen Sie den Benutzer nicht zu /the/result/page umleiten, indem Sie den Header Location folgendermaßen einrichten:

$cat process.php
<?php 
     process POST data here
     ... 
     header('Location: /the/result/page');
     exit();
?>

 enter image description here

Nachdem Sie POSTed-Daten verarbeitet haben, machen Sie einen kleinen <script> und das Ergebnis /the/result/page.

<?php 
     process POST data here
     render the <script>         // see below
     render `/the/result/page`   // OK
?>

Der <script>, den Sie rendern sollten:

<script>
    window.onload = function() {
        history.replaceState("", "", "/the/result/page");
    }
</script>

Das Ergebnis ist:

 enter image description here

wie Sie sehen können, sind die Formulardaten zu process.php-Skript POSTed.
Dieses Skript verarbeitet POSTed Daten und macht /the/result/page gleichzeitig mit:

  1. keine Weiterleitung
  2. keine rePOST-Daten beim Aktualisieren der Seite (F5) 
  3. no rePOST, wenn Sie durch den Browserverlauf zur vorherigen/nächsten Seite navigieren

UPD

Als eine andere Lösung frage ich feature request das Mozilla FireFox -Team, das Benutzern die Einrichtung eines NextPage-Headers ermöglicht, der wie Location-Header funktioniert und post/redirect/get-Muster veraltet macht.

Zusamenfassend. Wenn der Server die POST-Daten erfolgreich verarbeitet, geschieht Folgendes:

  1. Setup NextPage-Header statt Location
  2. Rendern Sie das Ergebnis der Verarbeitung von POST-Formulardaten wie für GET-Anforderungen in post/redirect/get-Muster

Der Browser wiederum zeigt den Header NextPage:

  1. Passen Sie window.location mit dem Wert NextPage an
  2. Wenn der Benutzer die Seite aktualisiert, handelt der Browser eine GET-Anforderung an NextPage aus, anstatt rePOST-Formulardaten

Ich denke, das wäre ausgezeichnet, wenn es umgesetzt würde, nicht? =)

7
Eugen Konkov

Ein ziemlich sicherer Weg ist, eine eindeutige ID in den Post zu implementieren und diese im Cache zu speichern 

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

Dann tun Sie dies in Ihrem Code:

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;
}
7
Absolut

Leiten Sie es einfach auf dieselbe Seite um, nachdem Sie die Formulardaten verwendet haben. Ich habe es ausprobiert.

header('location:yourpage.php');
4
krsoni

Eine verfeinerte Version von Moobs Post. Erstellen Sie einen Hash des POST, speichern Sie ihn als Sitzungscookie und vergleichen Sie bei jeder Sitzung Hashes.

// 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
}
3
skibulk

Rufen Sie nach dem Einfügen in die Datenbank die Methode unset () auf, um die Daten zu löschen. 

unset ($ _ POST);

Um das Einfügen von Aktualisierungsdaten zu verhindern, führen Sie nach dem Einfügen des Datensatzes eine Seitenumleitung auf dieselbe oder eine andere Seite durch. 

header ('Location:'. $ _ SERVER ['PHP_SELF']);

2
Thinesh

Grundsätzlich müssen Sie die Seite aus dieser Seite umleiten, aber es kann immer noch ein Problem sein, wenn Ihr Internet langsam ist.

Beispiel für ein Basisszenario:

Klicken Sie zweimal auf die Schaltfläche "Senden"

Weg zu lösen

  • Client-Seite

    • Deaktivieren Sie die Schaltfläche "Senden", sobald der Client darauf klickt
    • Wenn Sie Jquery verwenden: Jquery.one
    • PRG-Muster
  • Serverseite

    • Verwenden von differenzbasiertem Hash-Zeitstempel/Zeitstempel, wenn die Anforderung gesendet wurde.
    • Benutzeranfragenmarker. Wenn der Hauptladevorgang erfolgt, weisen Sie eine temporäre Anforderung zu, um diese zu ignorieren.
2
ZenithS

So verhindern Sie die Wiedervorlage von PHP-Formularen ohne Umleitung. Wenn Sie $ _SESSION (nach session_start) und ein $ _POST-Formular verwenden, können Sie Folgendes tun:

if ( !empty($_SESSION['act']) && !empty($_POST['act']) && $_POST['act'] == $_SESSION['act'] ) {
  // do your stuff, save data into database, etc
}

In Ihrem HTML-Formular fügen Sie Folgendes ein:

<input type="hidden" id="act" name="act" value="<?php echo ( empty($_POST['act']) || $_POST['act']==2 )? 1 : 2; ?>">
<?php
if ( $_POST['act'] == $_SESSION['act'] ){
    if ( empty( $_SESSION['act'] ) || $_SESSION['act'] == 2 ){
        $_SESSION['act'] = 1;
    } else {
        $_SESSION['act'] = 2;
    }
}
?>

Jedes Mal, wenn das Formular übermittelt wird, wird ein neuer Vorgang generiert, in einer Sitzung gespeichert und mit dem Nachakt verglichen.

Ps: Wenn Sie ein Get-Formular verwenden, können Sie einfach alle POST mit GET ändern.

1

Die Verwendung des Post/Redirect/Get-Musters von Keverw ist eine gute Idee. Sie sind jedoch nicht in der Lage, auf Ihrer Seite zu bleiben (und ich denke, das war es, wonach Sie gefragt haben?) Außerdem kann es manchmal fail :

Wenn ein Webbenutzer aktualisiert wird, bevor die erste Übermittlung abgeschlossen ist wegen Server-Verzögerung, was zu einer doppelten Anforderung von HTTP POST in .__ führt. bestimmte Benutzeragenten.

Eine andere Option wäre das Speichern in einer Sitzung, wenn der Text wie folgt in Ihre SQL-Datenbank geschrieben werden soll:

if($_SERVER['REQUEST_METHOD'] != 'POST')
{
  $_SESSION['writeSQL'] = true;
}
else
{
  if(isset($_SESSION['writeSQL']) && $_SESSION['writeSQL'])
  {
    $_SESSION['writeSQL'] = false;

    /* save $_POST values into SQL */
  }
}
0
Adam

Wie bereits erwähnt, ist es nicht möglich, Post/Redirect/Get nicht zu verwenden. Gleichzeitig ist es jedoch recht einfach, das zu tun, was Sie serverseitig tun möchten.

Auf Ihrer POST - Seite überprüfen Sie einfach die Benutzereingabe, bearbeiten diese jedoch nicht, sondern kopieren sie in ein SESSION-Array. Sie kehren dann wieder zur Haupt-Einreichungsseite zurück. Auf der Hauptseite Ihrer Übermittlungsseite wird geprüft, ob das von Ihnen verwendete SESSION-Array vorhanden ist. Falls ja, kopieren Sie es in ein lokales Array und löschen Sie es. Von dort aus können Sie darauf reagieren.

Auf diese Weise erledigen Sie Ihre gesamte Hauptarbeit nur einmal und erreichen, was Sie wollen.

0
Stu

Ich suchte nach einer Lösung, um die Wiedervorlage später in einem großen Projekt zu verhindern. Der Code funktioniert sehr gut mit $ _GET und $ _POST, und ich kann das Verhalten der Formularelemente nicht ändern, ohne das Risiko unvorhergesehener Fehler. __ Hier ist mein 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"] );

Es funktioniert nur, um die erneute Übermittlung von $ _POST und nicht von $ _GET zu vermeiden. Dies ist jedoch das Verhalten, das ich brauche .. Das Problem mit der erneuten Übermittlung funktioniert nicht mit Datei-Uploads!

0
Andreas Rex