2011-01-06 12 views
12

Ich habe eine Technik entwickelt, die das Übermitteln von doppelten Formularen verhindert, indem Sie die Seite zurück-/vorblättern oder die Seite aktualisieren. Und ich dachte darüber nach, es hier zu tun, ich habe bereits eine Probe nicht in der Produktionsumgebung getestet, was sind Fehler, die Sie identifizieren können?Doppelte Formulareinreichungen verhindern

Bitte beachten Sie, dass mir Form-Tokens bekannt sind, die Sie vor CSRF-Angriffen schützen und nicht in den folgenden Schritten hinzugefügt wurden.

Erzeugen Sie Formular-ID für jede Form, und es als verstecktes Feld im Formular:

$formid = microtime(true)*10000; 

- On Form einreichen:

  • Validate von Daten

  • Berechnen Sie den Hash der Formularfelder Daten

    $allvals = ''; 
    foreach($_POST as $k=>$v){ 
        $allvals .= $v; 
    } 
    $formHash = sha1($allvals); 
    
  • Überprüfen Sie den Hash-Wert des Formulars, indem Sie ihn mit zuvor gespeicherten Hashwerten vergleichen. Der Sitzungswert wird an jede Form durch die Variable $ formid gebunden.

    $allowAction = true; 
    if(isset($_SESSION['formHash'][$_POST['formid']]) && ($_SESSION['formHash'][$_POST['formid']] == $formHash)){ 
        $allowAction = false; 
    } 
    
  • Wenn der Formular-Hash nicht gefunden wurde, bedeutet dies, dass das Formular zum ersten Mal eingereicht oder die Formulardaten geändert wurden.
  • Wenn Daten (zur Datenbank, zum Beispiel) gespeichert, Form Hash-Sitzung speichern:

    $_SESSION['formHash'][$_POST['formid']] = $formHash; 
    

Vollversion des Codes: http://thebusy.me/2011/01/06/preventing-duplicate-form-submissions/

+0

Betrachten Sie Ihre Hash-Schnipsel gegen '$ formHash = SHA1 (serialisiert ($ _ POST)) Benchmarking;'. Es wird auch Hash-Tasten, die möglicherweise oder nicht vorteilhaft sein. – Dan

+0

Möglicherweise/dup Zusammenhang, http://stackoverflow.com/questions/4614052/how-to-prevent-multiple-form-submission-on-multiple-clicks-in-php/4614310#4614310 – user562374

+0

Mögliche Duplikat http://stackoverflow.com/questions/218907/how-to-handle-multiple-submissions-server-side –

Antwort

7

Eine einfachere Art und Weise, was zu erreichen Sie will ist redirect bei submit zu verwenden. Nachdem Sie eine POST-Anfrage bearbeitet haben, leiten Sie diese möglicherweise sogar auf die gleiche Seite um. Dies ist ein übliches Muster, das "Redirect after POST" oder POST/Redirect/GET genannt wird.

Zum Beispiel:

<?php 
if($_POST) { 
    // do something 

    // now redirect 
    header("Location: " . $_SERVER["REQUEST_URI"]); 
    exit; 
} 
?> 

<html> ... 
<form method="post" action=""> ... </form> 

Durch die Aktion „auf“ dann wird es an sich selbst vorlegen, bei dem der Punkt if ($ _ POST) Codeblock auf true validieren und das Formular verarbeiten, dann umleiten zurück zu sich selbst.

Natürlich möchten Sie wahrscheinlich auf eine andere Seite umleiten, die eine "Ihr Formular wurde gesendet" -Antwort zeigt oder das Formular auf eine andere Seite setzen und den HTML-Code dieser Seite als Antwort haben.

Der Vorteil dieser Methode besteht darin, dass beim Drücken der Zurück-Taste eine GET-Anfrage erfolgt, damit das Formular nicht erneut gesendet wird.

Bei Firefox wird die Einreichung tatsächlich aus dem Browserverlauf übernommen. Wenn Benutzer im Web surfen und dann zurückschlagen, sehen sie statt der "Danke" -Seite die Formularseite.

+0

Ja, ich lese darüber, und ich werde es für zukünftige Projekte verwenden. Das Problem betrifft meine aktuellen Websites, ich verwende Formulartokens und möchte die Struktur des Codes nicht durch Umleiten auf andere Seiten ändern. Vielen Dank @ newz2000 – isogashii

+1

Sie könnten sogar einen Schritt weiter gehen, um eine Dankesnachricht zu ermöglichen. Setup 2 Divs, eins mit der Form und eins mit der Dankesnachricht. Stellen Sie dann das Dankeschön-Feld ein: none in css. ? Haben Sie die Umleitung zurück zu formpage.php thankyou = 1 if ($ _GET [ 'thankyou'] == 1) {CSS, um das Formular div Anzeige keine zu machen, und stellen Sie die vielen Dank an display: block} – MSD

+5

Diese muss mit Form-Tokens kombiniert werden, um narrensicher zu sein. Wenn der Benutzer während der POST-Anforderung aktualisiert oder erneut übermittelt wird, erhalten Sie eine doppelte Anforderung. – bcoughlan

1

Es sieht so aus, als ob Sie damit zu kompliziert werden.Mein Lieblings-Weg, weil es auch eine Sitzung Aufbocken Hacks zugleich verhindert, ist hier beschrieben:

http://www.spotlesswebdesign.com/blog.php?id=11

Es ist einfach und leicht auf jeder Form impliment. Es verwendet eine zufällig generierte Seiteninstanz-ID, um zu verifizieren, dass die empfangene Formularvorlage mit der letzten Seite identisch ist, die für diesen bestimmten Nutzer geschaltet wurde.

+2

danke für die Antwort, aber die Post heißt es: „Es ist wichtig, Ihre Formularverarbeitungslogik auftreten haben, bevor Sie die neue Session-Seite Instanz-ID für diese an die Arbeit , obwohl es Möglichkeiten gibt. " Versuchen Sie, zwei Seiten gleichzeitig zu öffnen, das Senden der ersten wird nicht funktionieren, da die neue Seiten-ID generiert wird, wenn die zweite Seite geöffnet wird, das ist die Schwäche dieser Technik. Sie können jedoch ein Array von generierten Seiten-IDs verwenden und diese gegen sie überprüfen und die passende aus dem Array entfernen. – isogashii

+0

Guter Punkt. Das Array ist eine großartige Idee. – dqhendricks

+0

@isogashii Ich habe den Artikel geändert, um die Array-basierte Methode widerzuspiegeln. – dqhendricks

-1

Beide oben genannten Lösungen sind gut, aber ein bisschen kurz.

wie etwa weitere Einfügungen in den nächsten Minuten von demselben Benutzer mit vielleicht geringfügigen Änderungen in Daten zu stoppen?

Dies kann getan werden, indem man einen md5-Hash in einen Cookie auf dem Benutzerrechner legt und eine Kopie in der Datenbank speichert - auf diese Weise kann jeder weitere Versuch von demselben Rechner über eine bestimmte Zeit hinweg ignoriert und gestoppt werden die Datenbank.

vielleicht jemand über die Gültigkeit und Wirksamkeit von meinem Vorschlag kommentieren, oder bin ich den Holzweg ???

Verwandte Themen