Wie kann verhindert werden, dass Formulare mehrmals vom Client gesendet werden?

96

Manchmal, wenn die Antwort langsam ist, kann man mehrmals auf die Schaltfläche "Senden" klicken.

Wie kann dies verhindert werden?

Oh mein Gott
quelle
4
Ich hoffe, der Grund, warum Sie "Client-Seite" in Ihren Fragentitel einfügen, ist, dass Sie sich bewusst sind, dass jede Lösung auf dem Client, um betrügerische Übermittlungen zu vermeiden, 100% unsicher ist und Sie immer eine Validierung auf der Serverseite durchführen sollten.
Paolo Bergantino
51
Paolo: Ja, wenn Sie an vollständiger Datensicherheit interessiert sind, sollte dies serverseitig erfolgen. Aber manchmal möchten Sie nur verhindern, dass Oma auf die Schaltfläche "Senden" doppelklickt, wenn nur ein einziger Klick erforderlich ist. In diesen Fällen ist Javascript vollkommen in Ordnung.
Simon East
1
Dies nur serverseitig zu tun, ist ebenfalls nicht 100% sicher, da Ihre erste Anfrage möglicherweise lange genug dauert, bis sie abgeschlossen ist, sodass die zweite weiß, dass sie nicht fortgesetzt werden sollte.
igorsantos07
Verhindert das Double-Submit-Cookie-Muster zur Verhinderung von CSRF-Angriffen nicht auch die Übermittlung mehrerer Formulare?
Martin Thoma

Antworten:

99

Verwenden Sie unauffälliges Javascript, um das Übermittlungsereignis im Formular zu deaktivieren, nachdem es bereits übermittelt wurde. Hier ist ein Beispiel mit jQuery.

BEARBEITEN: Problem beim Senden eines Formulars ohne Klicken auf die Schaltfläche "Senden" behoben. Danke, ichiban.

$("body").on("submit", "form", function() {
    $(this).submit(function() {
        return false;
    });
    return true;
});
Starx
quelle
4
Was passiert, wenn das Formular durch Drücken der Eingabetaste in einem Textfeld gesendet wird?
Ichiban
2
Benötigen Sie überhaupt die return true? Ich denke, die erste Einreichung sollte ohne das funktionieren.
Simon East
Ich glaube, das return trueist impliziert, wenn es weggelassen wird.
Derek
15
Ich habe diese Lösung mit unauffälliger Validierung und MVC ausprobiert. Das JS wird zuerst aufgerufen, was immer false zurückgibt, und dann wird die Validierung aufgerufen. Wenn mein Formular einen Validierungsfehler aufweist, wird das Formular nie gesendet !!
Bjan
6
funktioniert wirklich toll. Ich möchte auch die Schaltfläche "Senden" deaktivieren und den Text der Schaltfläche "Senden" ersetzen, um auch einen Benutzertipp anzuzeigen. $(this).find("input[type='submit']").attr('disabled', 'disabled').val('submiting'); return true; });
Cam Song
42

Ich habe die Lösung von vanstee zusammen mit der unauffälligen Validierung von asp mvc 3 ausprobiert. Wenn die Client-Validierung fehlschlägt, wird der Code weiterhin ausgeführt und das Senden von Formularen ist endgültig deaktiviert. Ich kann nach Korrektur der Felder nicht erneut einreichen. (siehe Kommentar von bjan)

Also habe ich Vanstees Skript folgendermaßen geändert:

$("form").submit(function () {
    if ($(this).valid()) {
        $(this).submit(function () {
            return false;
        });
        return true;
    }
    else {
        return false;
    }
});
m irina
quelle
Gibt es noch andere Nebenwirkungen, die Sie beachten sollten, oder hat sich herausgestellt, dass Sie diese überall anwenden können?
Ciaran Gallagher
24

Die clientseitige Kontrolle der Formularübermittlung kann sehr elegant erreicht werden, indem der Onsubmit-Handler die Übermittlungsschaltfläche ausblendet und durch eine Ladeanimation ersetzt. Auf diese Weise erhält der Benutzer sofort visuelles Feedback an derselben Stelle, an der seine Aktion (das Klicken) stattgefunden hat. Gleichzeitig verhindern Sie, dass das Formular ein anderes Mal gesendet wird.

Wenn Sie das Formular über XHR senden, beachten Sie, dass Sie auch Übermittlungsfehler behandeln müssen, z. B. eine Zeitüberschreitung. Sie müssten die Schaltfläche "Senden" erneut anzeigen, da der Benutzer das Formular erneut senden muss .

In einem anderen Punkt bringt llimllib einen sehr gültigen Punkt vor. Alle Formularüberprüfungen müssen serverseitig erfolgen. Dies beinhaltet mehrere Übermittlungsprüfungen. Vertraue niemals dem Kunden! Dies ist nicht nur dann der Fall, wenn Javascript deaktiviert ist. Sie müssen berücksichtigen, dass der gesamte clientseitige Code geändert werden kann. Es ist schwer vorstellbar, aber das mit Ihrem Server sprechende HTML / Javascript ist nicht unbedingt das von Ihnen geschriebene HTML / Javascript.

Generieren Sie das Formular, wie von llimllib vorgeschlagen, mit einem für dieses Formular eindeutigen Bezeichner und fügen Sie es in ein verstecktes Eingabefeld ein. Speichern Sie diese Kennung. Beim Empfang von Formulardaten werden diese nur verarbeitet, wenn die Kennung übereinstimmt. (Verknüpfen Sie den Bezeichner auch mit der Benutzersitzung und stimmen Sie ihn aus Sicherheitsgründen ebenfalls ab.) Löschen Sie den Bezeichner nach der Datenverarbeitung.

Natürlich müssen Sie von Zeit zu Zeit die Kennungen bereinigen, für die nie Formulardaten übermittelt wurden. Aber höchstwahrscheinlich verwendet Ihre Website bereits eine Art "Garbage Collection" -Mechanismus.

rauben
quelle
15
<form onsubmit="if(submitted) return false; submitted = true; return true">
Chaos
quelle
6
Verwenden <form onsubmit="return (typeof submitted == 'undefined') ? (submitted = true) : !submitted">oder schreiben Sie var submitted = false;an der richtigen Stelle Ihres Skripts, um den folgenden Fehler zu vermeiden : Uncaught ReferenceError: submitted is not defined.
Tamás Bolvári
15

Hier ist eine einfache Möglichkeit, dies zu tun:

<form onsubmit="return checkBeforeSubmit()">
  some input:<input type="text">
  <input type="submit" value="submit" />
</form>

<script type="text/javascript">
  var wasSubmitted = false;    
    function checkBeforeSubmit(){
      if(!wasSubmitted) {
        wasSubmitted = true;
        return wasSubmitted;
      }
      return false;
    }    
</script>
Ichiban
quelle
Bei der unauffälligen jQuery-Validierung wird das Blockierungsskript zuerst aufgerufen und als nächstes die Validierung, die bei Validierungsfehlern überhaupt keine
Übermittlung
8

Deaktivieren Sie die Senden-Schaltfläche kurz nach einem Klick. Stellen Sie sicher, dass Sie die Validierungen ordnungsgemäß durchführen. Behalten Sie außerdem eine Zwischenseite für alle Verarbeitungs- oder DB-Vorgänge bei und leiten Sie dann zur nächsten Seite weiter. Dadurch wird sichergestellt, dass beim Aktualisieren der zweiten Seite keine weitere Verarbeitung durchgeführt wird.

Shoban
quelle
Ja, toller Tipp Shoban, ich stimme zu. Sollte seinform page ---submits to---> form_submission_script.php ---after saving, redirects to---> form_thankyou.html
Simon East
6

Hash die aktuelle Zeit, mache es zu einer versteckten Eingabe im Formular. Überprüfen Sie auf der Serverseite den Hash jeder Formularübermittlung. Wenn Sie diesen Hash bereits erhalten haben, erhalten Sie eine wiederholte Übermittlung.

Bearbeiten: Sich auf Javascript zu verlassen ist keine gute Idee, daher können Sie alle diese Ideen weiter abstimmen, aber einige Benutzer haben sie nicht aktiviert. Die richtige Antwort ist, Benutzereingaben auf der Serverseite nicht zu vertrauen.

llimllib
quelle
Sehen Sie nicht "zu viel" aus? ;-)
Shoban
1
Das klingt so, als würde es einen Benutzer nur davon abhalten, das Formular mehr als einmal pro Sekunde zu senden. Wenn ich das Formular um 2009-05-29 12:13:37 abschicke, lässt mich der Server kein weiteres Formular mit demselben Hash senden. Wenn ich jedoch auf Senden um 2009-05-29 12:13:38 geklickt habe, es würde durchgehen. Außerdem würde Ihre Technik verhindern, dass zwei verschiedene Benutzer gleichzeitig zwei verschiedene Formulare einreichen: Einer von ihnen wird rausgeschmissen, obwohl dies möglicherweise die erste Einreichung von ihm wäre.
Sarah Vessels
2
@moneypenny Ihr erster Einwand ist falsch. Der Hash bezieht sich auf den Zeitpunkt, zu dem das Formular an den Benutzer gesendet wurde, nicht auf den Zeitpunkt, zu dem er es übermittelt. Wenn Sie sich wirklich Sorgen um die Sekunde machen, haben Sie viele Möglichkeiten. Fügen Sie ihre Sitzungs-ID zu der Zeichenfolge hinzu, die Sie hashen, und / oder überprüfen Sie alle Felder des Formulars auf genaue Gleichheit. Zwei Benutzer haben wahrscheinlich nicht genau das gleiche Formular gesendet.
llimllib
@ Shoban Es tut mir leid, ich folge nicht, was Sie sagen
llimllib
2
"Übermäßig" liegt im Auge des Betrachters. Wenn Sie doppelte Formularübermittlungen wirklich verhindern müssen, muss zumindest ein Teil der Lösung serverseitig sein. "Sie können Benutzern nicht vertrauen."
Ben Blank
5

Sie können auch einen Fortschrittsbalken oder einen Drehfeld anzeigen, um anzuzeigen, dass das Formular verarbeitet wird.

Tony Borf
quelle
5

Mit JQuery können Sie Folgendes tun:

$('input:submit').click( function() { this.disabled = true } );

&

   $('input:submit').keypress( function(e) {
     if (e.which == 13) {
        this.disabled = true 
     } 
    }
   );
Boris Guéry
quelle
1
Was passiert, wenn das Formular durch Drücken der EINGABETASTE in einem Textfeld gesendet wird, nachdem die Schaltfläche deaktiviert wurde?
Ichiban
Wenn Sie die Schaltfläche auf diese Weise deaktivieren, kann der Benutzer dann nicht die EINGABETASTE drücken. Aber richtig, es muss ein Tastendruck auf die Submit-Eingabe
gebunden werden
Dies verhindert, dass die Schaltfläche gesendet wird. Deaktivieren Sie daher die serverseitige Validierung.
Marko Aleksić
@ Marko, richtig, aber das ist das OP, nach dem gefragt wird. Die Verwendung eines Tokens würde verhindern, dass das Formular zweimal gesendet wird.
Boris Guéry
1
Als ich diese Art von Technik ausprobierte, stellte ich fest, dass das Formular überhaupt nicht gesendet werden würde (zumindest nicht in Chrome 14), vermutlich weil Sie die Schaltfläche deaktivieren, bevor der Browser das Senden des Formulars startet.
Simon East
4

Ich weiß, dass Sie Ihre Frage mit "Javascript" markiert haben, aber hier ist eine Lösung, die überhaupt nicht von Javascript abhängt:

Es ist ein Webapp-Muster namens PRG , und hier ist ein guter Artikel , der es beschreibt

Pablo Fernandez
quelle
4

Sie können das mehrfache Senden einfach verhindern mit:

var Workin = false;

$('form').submit(function()
{
   if(Workin) return false;
   Workin =true;

   // codes here.
   // Once you finish turn the Workin variable into false 
   // to enable the submit event again
   Workin = false;

});
Alpha
quelle
Das Problem mit Ihrer Antwort ist, dass zwischen dem Klicken des Benutzers und der Zeit ein Sekundenbruchteil liegt Workin =true;. Doppelte Einreichungen sind weiterhin möglich, aber weniger wahrscheinlich.
Sent1nel
4

Die einfachste Antwort auf diese Frage lautet: "Manchmal, wenn die Antwort langsam ist, kann man mehrmals auf die Schaltfläche" Senden "klicken. Wie kann dies verhindert werden?"

Deaktivieren Sie einfach die Schaltfläche zum Senden von Formularen, wie im folgenden Code angegeben.

<form ... onsubmit="buttonName.disabled=true; return true;">
  <input type="submit" name="buttonName" value="Submit">
</form>

Die Schaltfläche "Senden" wird beim ersten Klicken zum Senden deaktiviert. Auch wenn Sie einige Validierungsregeln haben, funktioniert dies einwandfrei. Hoffe es wird helfen.

Imran Khan
quelle
Ich denke, Sie vermissen etwas, bitte posten Sie Ihren Code.
Imran Khan
3

Auf der Clientseite sollten Sie die Schaltfläche "Senden" deaktivieren, sobald das Formular mit Javascript-Code wie der von @vanstee und @chaos bereitgestellten Methode gesendet wurde.

Es gibt jedoch ein Problem mit Netzwerkverzögerungen oder Situationen mit deaktiviertem Javascript, in denen Sie sich nicht auf JS verlassen sollten, um dies zu verhindern.

Also, auf der Server-Seite , sollten Sie die wiederholte Einreichung von den gleichen Kunden überprüfen und lassen die man wiederholt , die einen falschen Versuch , von dem Benutzer scheint.

steveyang
quelle
Ich weiß, dass dies vor langer Zeit beantwortet wurde, aber kann jemand erklären, wie eine Netzwerkverzögerung die Deaktivierung verhindern kann? Ich beschäftige mich gerade mit diesem Problem und bin sehr verwirrt darüber, wie ein Formular doppelt gesendet wurde, obwohl ich die Schaltfläche deaktiviere. Ich habe noch nie darüber nachgedacht, dass JavaScript deaktiviert ist. Ich denke nicht, dass dies das Problem in meinem Fall ist, aber es ist trotzdem eine interessante Erkenntnis.
Davidatthepark
Ich dachte auch darüber nach, den Klick-Handler zu drosseln.
Davidatthepark
3

Sie können das Safeform JQuery Plugin ausprobieren.

$('#example').safeform({
    timeout: 5000, // disable form on 5 sec. after submit
    submit: function(event) {
        // put here validation and ajax stuff...

        // no need to wait for timeout, re-enable the form ASAP
        $(this).safeform('complete');
        return false;
    }
})
Max Kamenkov
quelle
1

Die einfachste und eleganteste Lösung für mich:

function checkForm(form) // Submit button clicked
{
    form.myButton.disabled = true;
    form.myButton.value = "Please wait...";
    return true;
}

<form method="POST" action="..." onsubmit="return checkForm(this);">
    ...
    <input type="submit" name="myButton" value="Submit">
</form>

Link für mehr ...

Solis
quelle
1

Verwenden Sie diesen Code in Ihrem Formular. Es werden mehrere Klicks verarbeitet.

<script type="text/javascript">
    $(document).ready(function() {
        $("form").submit(function() {
            $(this).submit(function() {
                return false;
            });
            return true;
        });     
    }); 
</script>

es wird sicher funktionieren.

Bachas
quelle
1

Dies ermöglicht das Senden alle 2 Sekunden. Im Falle einer Frontvalidierung.

$(document).ready(function() {
    $('form[debounce]').submit(function(e) {
        const submiting = !!$(this).data('submiting');

        if(!submiting) {
            $(this).data('submiting', true);

            setTimeout(() => {
                $(this).data('submiting', false);
            }, 2000);

            return true;
        }

        e.preventDefault();
        return false;
    });
})
Aurel
quelle
0

Der beste Weg, um die Übermittlung mehrerer zu verhindern, besteht darin, einfach die Schaltflächen-ID in der Methode zu übergeben.

    function DisableButton() {
        document.getElementById("btnPostJob").disabled = true;
    }
    window.onbeforeunload = DisableButton; 
user2427182
quelle
0

Dies mit Javascript zu tun ist etwas einfach. Es folgt der Code, der die gewünschte Funktionalität bietet:

$('#disable').on('click', function(){
    $('#disable').attr("disabled", true);
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="disable">Disable Me!</button>

Rish
quelle
0

Die einfachste Lösung besteht darin, die Schaltfläche beim Klicken zu deaktivieren und nach Abschluss des Vorgangs zu aktivieren. So überprüfen Sie eine ähnliche Lösung auf jsfiddle:

[click here][1]

Und Sie können eine andere Lösung für diese Antwort finden .

Kalyani
quelle
1
Während ein Link großartig ist, geben Sie bitte den Kontext zu Ihren Links an , da eine Antwort tatsächlich eine Antwort enthalten sollte. Beachten Sie, dass kaum mehr als ein Link zu einer externen Website ein möglicher Grund dafür ist, warum und wie einige Antworten gelöscht werden. .
Januar
0

Das funktioniert sehr gut für mich. Es sendet die Farm und macht die Schaltfläche deaktiviert und nach 2 Sekunden aktiv die Schaltfläche.

<button id="submit" type="submit" onclick="submitLimit()">Yes</button>

function submitLimit() {
var btn = document.getElementById('submit')
setTimeout(function() {
    btn.setAttribute('disabled', 'disabled');
}, 1);

setTimeout(function() {
    btn.removeAttribute('disabled');
}, 2000);}

In ECMA6 Syntex

function submitLimit() {
submitBtn = document.getElementById('submit');

setTimeout(() => { submitBtn.setAttribute('disabled', 'disabled') }, 1);

setTimeout(() => { submitBtn.removeAttribute('disabled') }, 4000);}
Awais Jameel
quelle
0

Nur um die möglichen Antworten zu ergänzen, ohne die Validierung der Browsereingaben zu umgehen

$( document ).ready(function() {
    $('.btn-submit').on('click', function() {
        if(this.form.checkValidity()) {
            $(this).attr("disabled", "disabled");
            $(this).val("Submitting...");
            this.form.submit();
        }
    });
});
Roi
quelle
0

Eine Alternative zu dem, was zuvor vorgeschlagen wurde, ist:

jQuery('form').submit(function(){
     $(this).find(':submit').attr( 'disabled','disabled' );
     //the rest of your code
});
Kisded Szabi - CodeRevolution
quelle