Wiedereinreichung des Formulars verhindern

107

Seite eins enthält ein HTML-Formular. Seite zwei - der Code, der die übermittelten Daten verarbeitet.

Das Formular auf Seite eins wird gesendet. Der Browser wird auf Seite zwei umgeleitet. Seite zwei behandelt die übermittelten Daten.

Wenn zu diesem Zeitpunkt die zweite Seite aktualisiert wird, wird die Warnung "Erneute Übermittlung des Formulars bestätigen" angezeigt.

Kann das verhindert werden?

Emanuil Rusev
quelle
3
Verwenden Sie Post Redirect Get wie hier beschrieben - >> en.wikipedia.org/wiki/Post/Redirect/Get
Meer
Sie können dies auch ohne Umleitung verhindern. Schauen Sie hier
Eugen Konkov

Antworten:

145

Es gibt zwei Ansätze, die hier verwendet werden:

Methode 1: Verwenden Sie AJAX + Redirect

Auf diese Weise veröffentlichen Sie Ihr Formular im Hintergrund mit JQuery oder ähnlichem wie Seite2, während der Benutzer weiterhin Seite1 anzeigt. Nach erfolgreicher Veröffentlichung leiten Sie den Browser auf Seite 2 um.

Methode 2: Post + Weiterleiten an sich selbst

Dies ist eine gängige Technik in Foren. Form on Page1 sendet die Daten an Page2, Page2 verarbeitet die Daten und führt die erforderlichen Schritte aus. Anschließend wird eine HTTP-Umleitung für sich selbst durchgeführt. Auf diese Weise ist die letzte "Aktion", an die sich der Browser erinnert, ein einfaches GET auf Seite 2, sodass das Formular bei F5 nicht erneut gesendet wird.

CodeTwice
quelle
2
Eine Variante von Methode 2 ist eine Weiterleitung auf eine andere Seite. Sie POSTEN beispielsweise an example.com/save.html und leiten nach Abschluss des Speichervorgangs zu example.com/list.html weiter .
Guillaume
1
Bei Methode 1 würde ich das jQuery-Plugin mit dem Namen BlockUI verwenden, um den Client über das Geschehen zu informieren.
Shikiryu
Ich verwende Methode 2, fordere mich jedoch auf, sie erneut einzureichen, wenn ich sie aktualisiere. Hat jemand ein ähnliches Problem?
scharf
Sind Sie sicher, dass die HTTP-Umleitung ordnungsgemäß funktioniert? Öffnen Sie den Netzwerkinspektor / firebug / was auch immer Ihr Browser hat, um ausgehende HTTP-Anforderungen zu überprüfen, und überprüfen Sie die HTTP-Aufrufe. Sie sollten sehen, dass die erste (das Posten der Formulardaten) mit der POST-Methode erfolgt und der HTTP-Code 301 mit dem auf sich selbst zeigenden Standortheader zurückgegeben wird. Anschließend sollte sofort eine weitere HTTP-Abfrage auf derselben Seite mit der GET-Methode angezeigt werden.
CodeTwice
@CodeTwice: In meinem Fall verarbeitet Seite1 Beiträge auf Seite2, Seite2 verarbeitet die Daten und zeigt eine Seite an (wobei Werte an die Vorlage übergeben werden). Wo soll die Umleitung erfolgen? .. Die Seite hat keine GET-Anforderungen.
user1050619
24

Sie müssen PRG - Post / Redirect / Get-Muster verwenden und haben gerade das P von PRG implementiert. Sie müssen umleiten . (Heute brauchen Sie überhaupt keine Umleitung mehr. Sehen Sie dies )

PRG ist ein Webentwicklungs-Entwurfsmuster, das doppelte Formularübermittlungen verhindert, dh Formular senden (Post Request 1) -> Redirect -> Get (Request 2)

Under the hood

Statuscode umleiten - HTTP 1.0 mit HTTP 302 oder HTTP 1.1 mit HTTP 303

Eine HTTP-Antwort mit Umleitungsstatuscode enthält zusätzlich eine URL im Feld für den Standortheader. Der Benutzeragent (z. B. ein Webbrowser) wird durch eine Antwort mit diesem Code aufgefordert, eine zweite, ansonsten identische Anforderung an die im Standortfeld angegebene neue URL zu senden.

Der Umleitungsstatuscode soll sicherstellen, dass der Browser des Webbenutzers in dieser Situation die Serverantwort sicher aktualisieren kann, ohne dass die anfängliche HTTP-POST-Anforderung erneut gesendet wird.

Double Submit Problem

Double Submit Problem

Post/Redirect/Get Solution

Lösung veröffentlichen / umleiten / abrufen

Quelle

Angelin Nadar
quelle
2
Gute Erklärung. Ich frage mich, was passieren wird, wenn der Benutzer nach der Weiterleitung im Browser auf die Schaltfläche "Zurück" klickt. Wird das Popup "Bestätigung der erneuten Übermittlung des Formulars" erneut angezeigt? Ich denke, auch wenn das Bestätigungs-Popup nicht erneut angezeigt wird, wird erneut eine Post-Anfrage auf Seite 1 mit denselben Daten gestellt, und der Benutzer wird erneut auf Seite 2 weitergeleitet. Ich habe eine Reihe von Formularen, Formular1, Formular2, Formular3. Wie kann man nahtlos von Form "n" zu Form "n-1" zurückkehren? Zufällige Frage: Wo haben Sie das PRG-Entwurfsmuster studiert
Rpant
@Rpant on Chrome Die PHP-Datei, die den Speicherort-Header sendet, wird nicht einmal im Browserverlauf angezeigt. Mit der Schaltfläche "Zurück" gelangen Sie einfach zurück zum Formular.
FluorescentGreen5
@Angelin Nach der Umleitung, wie erhalten die Daten? Zum Beispiel, wenn ich einige Daten an / some_url poste und nach / some_url umleitung, wodurch eine GET-Anfrage gestellt wird. Woher weiß ich, wie die Antwort lauten soll, da / some_url generisch ist und keine ID wie / some_url / <id> enthält?
Amit Tripathi
@AmitTripathi musst du selbst erstellen. Beispiel: Bei einer POST-Anforderung kann es sich um das Einfügen von Kundendaten handeln, während bei GET die erfolgreich eingefügten Daten angezeigt werden. Sie können die Daten als nichts anderes als die Formulardaten anzeigen oder die Ansicht der Kundenseite wiederverwenden, indem Sie die Kunden-ID, die Sie nach erfolgreichem Einfügen in die Datenbank erhalten haben, aus der Datenbank für diesen Kunden abrufen.
Angelin Nadar
Aber ich stimme der @ Eugen Konkov-Lösung zu
Angelin Nadar
10

Direkt kann man nicht, und das ist gut so. Die Warnung des Browsers ist aus einem bestimmten Grund vorhanden. Dieser Thread sollte Ihre Frage beantworten:

Verhindern Sie, dass die Schaltfläche Zurück die POST-Bestätigungswarnung anzeigt

Zwei wichtige Problemumgehungen waren das PRG-Muster und eine AJAX-Übermittlung, gefolgt von einer Skripterstellung.

Beachten Sie, dass wenn Ihre Methode eine GET- und keine POST-Übermittlungsmethode zulässt, dies sowohl das Problem löst als auch besser zur Konvention passt. Diese Lösungen werden unter der Annahme bereitgestellt, dass Sie Daten POSTEN möchten / müssen.

David
quelle
8

Die einzige Möglichkeit, 100% ig sicher zu sein, dass dasselbe Formular niemals zweimal gesendet wird, besteht darin, in jedes von Ihnen ausgegebene Formular eine eindeutige Kennung einzubetten und zu verfolgen, welche auf dem Server gesendet wurden. Die Gefahr besteht darin, dass dasselbe Formular nicht funktioniert, wenn der Benutzer auf der Seite, auf der sich das Formular befand, ein Backup erstellt und neue Daten eingibt.

Blrfl
quelle
6

Die Antwort besteht aus zwei Teilen:

  1. Stellen Sie sicher, dass doppelte Beiträge nicht mit Ihren Daten auf der Serverseite in Konflikt geraten. Betten Sie dazu eine eindeutige Kennung in den Beitrag ein, damit Sie nachfolgende Anforderungen serverseitig ablehnen können. Dieses Muster wird in Bezug auf Nachrichten als Idempotenter Empfänger bezeichnet .

  2. Stellen Sie sicher, dass der Benutzer nicht durch die Möglichkeit von doppelten Einsendungen durch beide gestört wird

    • Umleitung zu einem GET nach dem POST (POST-Umleitungs-GET-Muster)
    • Deaktivieren der Schaltfläche mit Javascript

Nichts, was Sie unter 2. tun, verhindert doppelte Übermittlungen vollständig. Die Leute können sehr schnell klicken und Hacker können trotzdem posten. Sie benötigen immer 1., wenn Sie absolut sicher sein möchten, dass keine Duplikate vorhanden sind.

iwein
quelle
2

Wenn Sie eine Seite mit POST-Daten aktualisieren, bestätigt der Browser Ihre erneute Übermittlung. Wenn Sie GET-Daten verwenden, wird die Meldung nicht angezeigt. Sie können auch die zweite Seite nach dem Speichern der Übermittlung auf eine dritte Seite ohne Daten umleiten lassen.

Joel
quelle
2

Ich fand, dass niemand diesen Trick erwähnte.

Ohne Umleitung können Sie die Formularbestätigung beim Aktualisieren weiterhin verhindern.

Standardmäßig lautet der Formularcode wie folgt:

<form method="post" action="test.php">

Ändern Sie es jetzt in <form method="post" action="test.php?nonsense=1">

Du wirst die Magie sehen.

Ich denke, das liegt daran, dass Browser das Popup für Bestätigungsalarme nicht auslösen, wenn sie eine GET-Methode (Abfragezeichenfolge) in der URL erhalten.

Markieren
quelle
1

Sie können dies mit jquery tun

<script>
   $(document).ready(function(){
   window.history.replaceState('','',window.location.href)
   });
</script>

Dies ist die eleganteste Methode, um zu verhindern, dass Daten nach der Übermittlung aufgrund von Rückmeldungen erneut gesendet werden.

Hoffe das hilft.

noobprogrammer
quelle
0

Das PRG-Muster kann nur die erneute Übermittlung verhindern, die durch die Seitenaktualisierung verursacht wird. Dies ist keine 100% sichere Maßnahme.

Normalerweise werde ich die folgenden Maßnahmen ergreifen, um eine erneute Einreichung zu verhindern:

  1. Client-Seite - Verwenden Sie Javascript, um doppelte Klicks auf eine Schaltfläche zu verhindern, die das Senden von Formularen auslösen. Sie können die Schaltfläche einfach nach dem ersten Klick deaktivieren.

  2. Serverseitig - Ich berechne einen Hash für die übermittelten Parameter und speichere diesen Hash in der Sitzung oder Datenbank. Wenn also die doppelte Übermittlung empfangen wurde, können wir die Überschneidung erkennen und dann die richtige Antwort an den Client senden. Sie können jedoch auf der Clientseite einen Hash generieren.

In den meisten Fällen können diese Maßnahmen dazu beitragen, eine erneute Einreichung zu verhindern.

ehe888
quelle
0

Ich mag die Antwort von @ Angelin wirklich. Wenn Sie jedoch mit Legacy-Code arbeiten, bei dem dies nicht praktikabel ist, funktioniert diese Technik möglicherweise für Sie.

Oben in der Datei

// Protect against resubmits
if (empty($_POST))  {
   $_POST['last_pos_sub'] = time();
} else {
     if (isset($_POST['last_pos_sub'])){
        if ($_POST['last_pos_sub'] == $_SESSION['curr_pos_sub']) {
           redirect back to the file so POST data is not preserved
        }
        $_SESSION['curr_pos_sub'] = $_POST['last_pos_sub'];
     }
}

Halten Sie sich dann am Ende des Formulars last_pos_subwie folgt fest:

<input type="hidden" name="last_pos_sub" value=<?php echo $_POST['last_pos_sub']; ?>>
Scott C Wilson
quelle
0

Versuchen Sie es mit tris:

function prevent_multi_submit($excl = "validator") {
    $string = "";
    foreach ($_POST as $key => $val) {
    // this test is to exclude a single variable, f.e. a captcha value
    if ($key != $excl) {
        $string .= $key . $val;
    }
    }
    if (isset($_SESSION['last'])) {
    if ($_SESSION['last'] === md5($string)) {
        return false;
    } else {
        $_SESSION['last'] = md5($string);
        return true;
    }
    } else {
    $_SESSION['last'] = md5($string);
    return true;
    }
}

Verwendung / Beispiel:

if (isset($_POST)) {
    if ($_POST['field'] != "") { // place here the form validation and other controls
    if (prevent_multi_submit()) { // use the function before you call the database or etc
        mysql_query("INSERT INTO table..."); // or send a mail like...
        mail($mailto, $sub, $body); // etc
    } else {
        echo "The form is already processed";
    }
    } else {
    // your error about invalid fields
    }
}

Schriftart: https://www.tutdepot.com/prevent-multiple-form-submission/

Rômulo ZC Cunha
quelle
0

Verwenden Sie js, um das Hinzufügen von Daten zu verhindern:

if ( window.history.replaceState ) {
    window.history.replaceState( null, null, window.location.href );
}
Tran Anh Hien
quelle