2010-01-25 4 views
29

Manchmal kann der Benutzer Enter zweimal drücken, und der Beitrag wird zweimal eingefügt.Wie verhindert man mehrere Einfügungen beim Einreichen eines Formulars in PHP?

Gibt es eine Lösung, dies zu verhindern, außer zu prüfen, ob es bereits einen Beitrag mit den gleichen title und content gibt?

+0

Können Sie das Ereignis deaktivieren, das beim Drücken von Enter ausgelöst wird? –

+12

Klatschen Sie sie jedes Mal, wenn sie es tun. Irgendwann werden sie lernen :) – Gordon

+4

Ich würde empfehlen, mit Form Keys. Sehen Sie sich das hier an: http: //net.tutsplus.com/tutorials/php/secure-your-forms-mit-form-keys/ –

Antwort

1

Deaktivieren Sie die Schaltfläche zum Senden mit Javascript, sobald das Formular gesendet wurde (onsubmit).

Beachten Sie, dass wenn der Benutzer Javascript deaktiviert hat, sie dennoch zweimal senden können. Ob dies oft genug geschieht, um auch das Einchecken Ihres Codes zu rechtfertigen (wie Sie es in Ihrer Frage vorgeschlagen haben) liegt ganz bei Ihnen.

0

Deaktivieren Sie die Senden-Schaltfläche, sobald der Benutzer das Formular mit JavaScript gesendet hat. Das verwendet beispielsweise StackOverflow, wenn Sie eine Frage beantworten.

Zum Beispiel

<input type="submit" onclick="this.disabled=true" /> 
0

einen JavaScript Verwenden Sie die Taste, sobald abzuschalten, wie es angeklickt wird.

onclick="this.disabled=true;forms[0].submit();" 
+1

Der 'Onclick'-Handler wird nicht ausgeführt, wenn das Formular über einen Tastaturstrich übergeben wird, z. Der Benutzer drückt die Eingabetaste, während er auf die Übermittlungsschaltfläche fokussiert ist. Verwenden Sie besser "onsubmit" wie eines der anderen vorgeschlagenen Poster. – Asaph

+1

@Asaph: Ich mag eigentlich die Token-Idee @Mats vorgeschlagen. Aber wenn Client-Seite bleiben würde, wäre es wahrscheinlich besser, eine Methode zu haben, die sowohl das Klicken als auch das Senden beinhaltet. 2 Mausklicks können im IE registriert werden, bevor das Übermitteln von Inhalten ausgelöst wird. Dumm, aber ich habe es gesehen. –

0

Durch zweimaliges Drücken einreichen ganz selten führt in mehreren Einsätzen, aber wenn man eine tote einfache sollution möchten, verwenden Sie

onsubmit="document.getElementById('submit').disabled = true" 

in dem Formular-Tag, vorausgesetzt, Sie geben Ihre Submit-Button id="submit"

30

Verwenden Sie ein eindeutiges Token mit der Post, so dass jeder Post/Postback nur einmal behandelt wird.

Deaktivieren der Schaltfläche "Senden" ist keine sehr gute Lösung, da die Leute JavaScript deaktiviert haben oder andere seltsame Dinge tun können. Die Validierung auf der Clientseite ist ein guter Anfang, sollte aber immer auch mit der serverseitigen Verarbeitung gesichert werden.

+2

+1 - dies ist die am häufigsten verwendete Methode und hat keine clientseitigen Abhängigkeiten. Warum wird dies nicht als Antwort akzeptiert? – Russell

+0

@Steve Nicht wahr. Es wird nicht erwartet, dass POSTs idempotent sind. – kaqqao

46

Es gibt mehrere Lösungen für dieses Problem:

  1. Verwenden Sie Javascript um die Form des Submit-Button zu deaktivieren, wenn es gebucht wird. Nachteil ist, dass dies ABSOLUT keine narrensichere Art ist. Es ist sehr einfach, Formulare zu senden, ohne tatsächlich auf die Schaltfläche zu klicken. Dies würde auch für Benutzer mit deaktiviertem JavaScript nicht funktionieren. Ich würde diese Methode definitiv nicht empfehlen.

    Beispiel:

    <script language="javascript"> 
    <!-- 
        function disableSubmitButton() { 
         // you may fill in the blanks :) 
        } 
    --> 
    </script> 
    <form action="foo.php" method="post"> 
        <input type="text" name="bar" /> 
        <input type="submit" value="Save" onclick="disableSubmitButton();"> 
    </form> 
    
  2. Verwenden PHP sessions eine Session-Variablen (zB $ _SESSION [ 'posttimer']) auf den aktuellen Zeitstempel auf Post setzen. Bevor Sie das Formular in PHP tatsächlich bearbeiten, prüfen Sie, ob die Variable $ _SESSION ['posttimer'] existiert und prüfen Sie auf einen bestimmten Zeitstempel-Unterschied (IE: 2 Sekunden). Auf diese Weise können Sie doppelte Anmeldungen einfach ausfiltern.

    Beispiel:

    // form.html 
    <form action="foo.php" method="post"> 
        <input type="text" name="bar" /> 
        <input type="submit" value="Save"> 
    </form> 
    
    // foo.php 
    if (isset($_POST) && !empty($_POST)) 
    { 
        if (isset($_SESSION['posttimer'])) 
        { 
         if ((time() - $_SESSION['posttimer']) <= 2) 
         { 
          // less then 2 seconds since last post 
         } 
         else 
         { 
          // more than 2 seconds since last post 
         } 
        } 
        $_SESSION['posttimer'] = time(); 
    } 
    
  3. Fügen Sie ein einzigartiges Token auf jeder POST. In diesem Fall würden Sie auch eine Sitzungsvariable für das Token festlegen, das Sie einschließen möchten, und anschließend das Token im Formular rendern. Sobald das Formular gesendet wurde, generieren Sie das Token erneut. Wenn das übermittelte Token nicht mit dem Token in Ihrer Sitzung übereinstimmt, wurde das Formular erneut gesendet und sollte für ungültig erklärt werden.

    Beispiel:

    // form.php 
    <?php 
        // obviously this can be anything you want, as long as it is unique 
        $_SESSION['token'] = md5(session_id() . time()); 
    ?> 
    <form action="foo.php" method="post"> 
        <input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" /> 
        <input type="text" name="bar" /> 
        <input type="submit" value="Save" /> 
    </form> 
    
    // foo.php 
    if (isset($_SESSION['token'])) 
    { 
        if (isset($_POST['token'])) 
        { 
         if ($_POST['token'] != $_SESSION['token']) 
         { 
          // double submit 
         } 
        } 
    } 
    
+3

+1 Große Antwort, aber ich würde bearbeiten, so dass Ihre Empfehlung zuerst kommt, und dann folgen Sie mit den Methoden, die Sie nicht empfehlen - würde für das Lesen erleichtern. Das heißt, es sollte die akzeptierte Antwort sein. –

+0

Für die JavaScript-Lösung könnten Sie diese Funktion für das Formular-Übermittlungs-Ereignis erstellen, nicht für das Senden von Schaltflächen klicken. Diese Funktion würde aufgerufen werden und würde die Senden-Schaltfläche deaktivieren. – machineaddict

+1

Es gesehen, dass Methode Drei perfekt ist – yip

1

Alternativ einmalige Form Schlüssel verwenden.

5

Generieren Sie einen einmaligen Schlüssel für die einmalige Verwendung, um mit dem Formular zu senden.

Sich auf Javascript zu verlassen, ist eine schlechte Idee, weil es möglicherweise vom Benutzer im Client deaktiviert wurde. Mit dem Schlüsselschema kann, wenn das Senden vom Server empfangen wird, die Übermittlung für diesen Schlüssel gesperrt werden. Sie können auf doppelte Übermittlungen antworten, wie Sie möchten.

Damit dieser Ansatz funktioniert, müssen Schlüssel eindeutig und schwer vorhersehbar sein. Andernfalls könnten einige Formulare aufgrund von Schlüsselkollisionen gesperrt werden. Damit Sie die Schlüssel nicht bei jeder Formularübermittlung verfolgen müssen und Konflikte vermeiden, sollten die Schlüssel mit der Sitzung des Benutzers ablaufen. Die andere Sache, auf die Sie achten sollten, ist, wenn böswillige Benutzer den Schlüssel vorhersagen können, ist Ihr Code anfällig für irgendeine Art von Hijacking oder DOS-Exploit.

+1

Dies ist der Ansatz, den ich verwende. Generieren Sie eine GUID, wenn die Seite gerendert wird, und fügen Sie diese beim Speichern eines Formulars in Ihre Datenbank ein. Stellen Sie sicher, dass GUID in der DB vor dem Einfügen nicht vorhanden ist. –

+1

Welche Art von GUID-Generierungsalgorithmus wird normalerweise verwendet? –

1

Ich benutze diese:

$form_token = $_SESSION['form_token'] = md5(uniqid()); 

$ form_token mit dem Formular schicken, dann ...

Ich überprüfe das form_token:

if($_SESSION['form_token'] != $_POST['form_token']) { 
    echo 'Error'; 
} 
-1

Aron Rotteveel der Fügen Sie ein einzigartiges Token auf jeder POST arbeitete für mich. Mein Formular wird jedoch immer noch übermittelt, wenn ein Benutzer die Seite aktualisiert (F5). Ich schaffte es, dies zu lösen, indem ein Reset-Zugabe:

  // reset session token 
      $_SESSION['token'] = md5($_POST['token'] . time()); 

meine letzte Skripte geht so:

if (isset($_SESSION['token'])) { 
    if (isset($_POST['token'])) { 
     if ($_POST['token'] != $_SESSION['token']) { 
      echo '<h3>Oops! You already submitted this request.</h3>'; 
     } else { 
      // process form 
      // reset session token 
      $_SESSION['token'] = md5($_POST['token'] . time()); 
     } 
    } else { 
     echo 'post token not set'; 
     $_SESSION['token'] = md5($somevariable . time()); 
    } 
} 

oh! Vergessen Sie nicht, session_start(); vor <!DOCTYPE>

hinzuzufügen Ich bin ein PHP-Neuling also bitte korrigieren Sie mich, wenn Sie Unregelmäßigkeiten finden.

+0

das ist nutzloser Code. Führen Sie einfach eine HTTP-Weiterleitung nach dem Senden des Formulars aus. –

+0

Ich möchte das tun, aber mein Formular funktioniert auf einer einzigen Seite. Ich möchte zunächst jquery entladen() verwenden, aber ich finde dies nützlich bei Gelegenheiten Benutzer versehentlich gedrückt f5 (Seite neu laden). Hast du einen Link in dieser Weiterleitung? Ich würde gerne überdenken – Pabile

+0

Ihr Grund macht keinen Sinn. Sie können auch eine HTTP-Weiterleitung auf der einzelnen Seite durchführen. –

-1

verwenden JavaScript, ihn zu stoppen von

+1

Beispiel/demo code würde Machen Sie dies zu einer potenziell wertvollen Antwort. – nickhar

0

Eine andere Möglichkeit, das Senden einer Bestätigungsseite zu erstellen, in dem Benutzer schließlich den Absenden-Button drücken. Es könnte die Möglichkeiten dieser Art reduzieren.

Verwandte Themen