Wie kann ich die HTML-Formularvalidierung vor der reCAPTCHA-Validierung verarbeiten?

Lesezeit: 11 Minuten

Benutzeravatar von Julio Guerra
Julio Guerra

Ich habe das neue versteckte reCAPTCHA (v2)-Framework integriert, das den Benutzer standardmäßig mit dem verifiziert click Ereignis des Submit-Buttons. Dieses Ereignis wird jedoch vor der integrierten HTML-Formularvalidierung ausgelöst. Ich suche nach einer Möglichkeit, es in der erwarteten Reihenfolge zu machen: zuerst Formularvalidierung, danach reCAPTCHA.

Benutzeravatar von Julio Guerra
Julio Guerra

Dank einer neuen Version v2 müssen Sie dies programmgesteuert tun grecaptcha Methode: grecaptcha.execute() damit recaptcha nicht das standardmäßige Klickereignis der Schaltfläche ersetzt, das die standardmäßige HTML5-Formularvalidierung verhinderte.

Der Ereignispfad lautet:

  1. Klickereignis der Schaltfläche „Senden“: Browserintegrierte Formularvalidierung
  2. Ereignis zum Senden des Formulars: Anruf grecaptcha.execute()
  3. reCAPTCHA-Rückruf: Senden Sie das Formular ab
$('#form-contact').submit(function (event) {
    event.preventDefault();
    grecaptcha.reset();
    grecaptcha.execute();
  });

function formSubmit(response) {
  // submit the form which now includes a g-recaptcha-response input
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js"></script>
<form action="?">
  <div class="g-recaptcha" 
       data-sitekey="your-key"
       data-size="invisible"
       data-callback="formSubmit">
  </div>
  <button type="submit">Submit</button>
</form>

  • Mit diesem Code wird das Formular niemals gesendet, da es die Standardaktion (das Senden) verhindert. Wenn Sie einreichen möchten, dürfen Sie die Aktion nicht aufgrund einer Bedingung verhindern, wie meine Antwort unten, bitte überprüfen Sie dort.

    – giovannipds

    10. März 2017 um 21:04 Uhr

  • @giovannipds dieser Code läuft auf unserer Website und übermittelt oO grecaptcha.execute() übermittelt es, WENN der reCAPTCHA-Formulartest korrekt durchgeführt wurde.

    – Julio Guerra

    14. März 2017 um 21:56 Uhr


  • @JulioGuerra du hast recht, aber es verwendet leider keine standardmäßige Browservalidierung. Ich denke, meins unten tut es. Versuchen Sie, es zu überprüfen.

    – giovannipds

    9. Juni 2017 um 18:25 Uhr

  • formSubmit() muss leer sein?!

    – Schwarz

    20. November 2017 um 22:18 Uhr

  • @Black nicht unbedingt. Der Dokumentation sagt “Die Antwort des Benutzers, g-recaptcha-response, wird die Eingabe für Ihre Rückruffunktion sein.” Ich habe das Beispiel geändert, um es einzuschließen, anstatt es zu ignorieren (weil Sie es auch aus einer versteckten Eingabe im Formular lesen können, sobald es validiert ist).

    – Julio Guerra

    21. November 2017 um 13:57 Uhr

Hier ist meine Lösung, um eine HTML5-Validierung + unsichtbares Recaptcha zu erhalten:

HTML:

<form id="my-form">
    <!-- Your form fields ... -->
    <div class="g-recaptcha"
        data-sitekey="..."
        data-callback="submitMyForm"
        data-size="invisible">
    </div>
    <button type="submit">Submit</button>
</form>

JS:

var myForm = $('my-form');

function submitMyForm () {
    myForm.trigger('submit', [true]);
}

$(function () {
    myForm.on('submit', function (e, skipRecaptcha) {
        if(skipRecaptcha) {
            return;
        }

        e.preventDefault();
        grecaptcha.execute();
    });
  })

Hallo habe hier eine funktionierende Lösung. Arbeiten mit unsichtbarem Recaptcha.

jQuery(document).ready(function() {
    var commentform = jQuery("#commentform");
    commentform.on("click", "#submit-comment", function(e) {
      if(commentform[0].checkValidity()) {
        e.preventDefault();
        grecaptcha.execute();
      }
    });
});

function submitCommentForm(data) {
    document.getElementById("commentform").submit();
}
<form action="blaba.php" method="post" id="commentform" class="comment-form">
  <div class="form-submit">
    <div data-callback="submitCommentForm" data-sitekey="yourkey" class="g-recaptcha" data-size="invisible">
    <button id="submit-comment">Leave a comment</button>
  </div>
</form>

Benutzeravatar von USD Matt
USD Matt

Ich hatte dieses Problem, da die Standardmethode die HTML5-Formularvalidierung zu überschreiben scheint. Ich wollte auch, dass der gesamte Code generisch ist, anstatt irgendwelche Funktionen/Elementnamen fest zu codieren. Am Ende kam ich mit der v3-API auf den folgenden Code –

HTML

<form method="post" action="?" class="ui-recaptcha" name="my_form_name">
   ...
   <input type="submit" value="Submit">
</form>
<script src="https://www.google.com/recaptcha/api.js?render={key}" async defer></script>

Javascript (ich verwende jQuery, wäre aber ziemlich einfach an Vanilla js anzupassen)

$('.ui-recaptcha').submit(e => {

    var form = e.target;

    if( $(form).data('recaptcha-done') )
        return;

    e.preventDefault();
    grecaptcha.execute('{key}', {'action': $(form).attr('name')}).then(token => {

        $(form).append($('<input>').attr({'type': 'hidden', 'name': 'g-recaptcha-response', 'value': token}));
        $(form).data('recaptcha-done', true);
        $(form).submit();
    });
});

Ich fand das gerade anrufen submit wie in einigen Beispielen oben verursachte eine Schleife für mich, was Sinn machen würde, da der Recaptcha-Handler auf dem läuft submit Fall.

Dies führt recaptcha für alle aus ui-recaptcha Formular, übergibt das Formular name -Attribut als Aktion, die in der reCaptcha-Konsole zu sehen ist, und fügt dann das Token in das Formular ein. Nach der Ausführung wird ein Datenattribut im Formular festgelegt, sodass der rekursive Aufruf zum Absenden nicht versucht, recaptcha erneut auszuführen.

Benutzeravatar von PigBoT
PigBoT

Hier ist meine Lösung.

  • Verwendet reCaptcha v3 (unsichtbar) Dokumente
  • Verwendet native HTML5-Formularvalidierung
  • Verwendet reines JS
  • Verwendet Standard-POST-Verarbeitung (kann in AJAX geändert werden)

Fügen Sie so viele Formulare wie nötig hinzu, ändern Sie einfach die „UNIQUE_FORM_ID“ an den beiden Stellen und aktualisieren Sie die POST_URL für das Formular. Stellen Sie sicher, dass Sie Ihren eigenen Schlüssel an den Speicherorten von „RECAPTCHA_SITE_KEY“ verwenden.

<form id="UNIQUE_FORM_ID" method="post" action="POST_URL">
    <!-- ** Notice ** this hidden input field that will later send our g-recaptcha token back to our server -->
    <input type="hidden" name="g-recaptcha-response" value="">
    <!-- Add other hidden nonce fields -->

    <!-- Required field -->
    <input name="fullname" type="text" placeholder="Full Name" required>

    <!-- Submit button -->
    <!-- ** Notice ** the 'form' attribute; using SAME value as it's parent's form id, above. -->
    <!-- ** Notice ** the 'onclick' attribute; be sure to pass event -->
    <button type="submit" form="UNIQUE_FORM_ID" onclick="formSubmitBtn(event)">Send</button>
</form>

<!-- Only add scripts once -->
<!-- ** Notice ** to manually call grecaptcha, our site key must be included when loading api.js using the 'render' query param -->
<script src="https://www.google.com/recaptcha/api.js?render=RECAPTCHA_SITE_KEY"></script>
<script>
    /**
     * Handles form submissions for Google recaptcha v3.
     * Allows for HTML5 form validation to complete before processing.
     */
    function formSubmitBtn($event) {
        /**
         * Checks the validity of the form.
         * Return if invalid; HTML5 validation errors should display.
         */
        if (!$event.target.form.checkValidity()) {
            return;
        }
        /**
         * Form is client-side valid; taking over the remainder of processing.
         */
        $event.preventDefault();
        grecaptcha.ready(function() {
            grecaptcha.execute("RECAPTCHA_SITE_KEY", { action: 'submit' }).then(function(token) {
                /**
                 * Adds the token g-recaptcha-response token to our hidden form element.
                 * ** Notice ** we our referencing the specific form's input element by name here (do not use IDs).
                 */
                $event.target.form.elements['g-recaptcha-response'].value = token;
                /**
                 * Use the form API directly to submit the form.
                 */
                $event.target.form.submit();
            });
        });
    }
</script>

  • Ich bin über deinen Beitrag für eine ähnliche Lösung gestolpert. Soll dies rein clientseitig sein? Das Token scheint nicht ausgefüllt zu sein. Zweitens, gibt es einen Grund, warum Sie sich entschieden haben, es nicht zu verwenden? addEventListener z.B document.addEventListener('DOMContentLoaded', function () { document.getElementById('html-submitt') .addEventListener('submit', formSubmitBtn); });

    – Motiviert

    10. Januar 2021 um 3:47 Uhr


  • Dies soll flexibel sein. Es gibt keine Serverabhängigkeit, wenn Sie danach fragen. Natürlich müssen Sie Ihre privaten API-Schlüssel verwenden, um das Antworttoken an Google zu senden, um die Recaptcha-Werte zu erhalten. Hast du getauscht RECAPTCHA_SITE_KEY mit Ihrem speziellen Schlüssel? Ich führe diesen Code in einer Produktionsumgebung aus und er funktioniert für mich. Ich sehe keinen Grund, Ereignis-Listener hinzuzufügen und Ressourcen zu verbrauchen und Speicherlecks zu riskieren, wenn Ereignis-Listener usw. nicht entfernt werden (je nach Verwendung). Die eine Funktion unterstützt unbegrenzte Formulare. Helfe gerne weiter. Code-Auszug?

    – PigBoT

    10. Januar 2021 um 20:59 Uhr

  • Der Code wird wörtlich mit einem aktualisierten Recaptcha-Schlüssel ausgeführt. Wenn das Formular gesendet wird, führt es die native HTML5-Validierung durch (was ein Plus ist). Es erfasst dann die Werte, z. B. den Namen. Es gibt jedoch kein Token in der verborgenen Eingabe zurück. Es ist leer. Der Grund für die Verwendung von Ereignis-Listenern liegt darin, dass Inline-Klickereignisse durch Inhaltssicherheitsrichtlinien blockiert werden.

    – Motiviert

    10. Januar 2021 um 21:59 Uhr

  • Ich bin kein CSP-Experte. Viele Fragen – aber nicht der Platz in diesen Kommentaren. : P Es klingt wie eine vernünftige Problemumgehung für Ihre Situation. Es gibt so viele Orte, an denen die Änderung schief gehen könnte, insbesondere in der Umgebung $event. Kommt es immer noch wie erwartet durch? Wird aus dem Token erstellt execute Methode? Wird der Token-Wert an das richtige Formular angehängt? Wenn Sie einen Codepen oder ähnliches erstellen, könnte ich beim Debuggen helfen.

    – PigBoT

    11. Januar 2021 um 15:28 Uhr

  • Ich bin mir nicht sicher, ob Codepen oder etwas Ähnliches die Möglichkeit hat, eine CSP-Richtlinie zu implementieren, da dies in der Regel serverseitig ist. Teilen Sie gerne die Inhaltssicherheitsrichtlinie, wenn Sie möchten. Meinst du, es kommt beim Laden durch? Wenn ja, nein, es ist kein Token geladen. Auch beim Absenden des Formulars wird kein Token generiert. Der versteckte Wert ist leer.

    – Motiviert

    11. Januar 2021 um 21:34 Uhr

Benutzeravatar von Zoran
Zoran

 let siteKey = "...";
 $("form").submit(function (eventObj) {
        var myForm = this;
        eventObj.preventDefault();
        grecaptcha.execute( siteKey, {
            action: "submit"
        })
            .then(function (token) {
                $('<input />').attr('type', 'hidden')
                    .attr('name', "g_recaptcha_response")
                    .attr('value', token)
                    .appendTo(myForm);
                myForm.submit();
            });
    });

Dadurch wird recapcha ausgeführt, auf die Antwort gewartet, das versteckte Attribut g_recaptcha_response zu jedem Formular hinzugefügt, wenn der Browser versucht, es zu senden, und es dann tatsächlich gesendet. Sie benötigen die globale Variable siteKey

  • Ich bin über deinen Beitrag für eine ähnliche Lösung gestolpert. Soll dies rein clientseitig sein? Das Token scheint nicht ausgefüllt zu sein. Zweitens, gibt es einen Grund, warum Sie sich entschieden haben, es nicht zu verwenden? addEventListener z.B document.addEventListener('DOMContentLoaded', function () { document.getElementById('html-submitt') .addEventListener('submit', formSubmitBtn); });

    – Motiviert

    10. Januar 2021 um 3:47 Uhr


  • Dies soll flexibel sein. Es gibt keine Serverabhängigkeit, wenn Sie danach fragen. Natürlich müssen Sie Ihre privaten API-Schlüssel verwenden, um das Antworttoken an Google zu senden, um die Recaptcha-Werte zu erhalten. Hast du getauscht RECAPTCHA_SITE_KEY mit Ihrem speziellen Schlüssel? Ich führe diesen Code in einer Produktionsumgebung aus und er funktioniert für mich. Ich sehe keinen Grund, Ereignis-Listener hinzuzufügen und Ressourcen zu verbrauchen und Speicherlecks zu riskieren, wenn Ereignis-Listener usw. nicht entfernt werden (je nach Verwendung). Die eine Funktion unterstützt unbegrenzte Formulare. Helfe gerne weiter. Code-Auszug?

    – PigBoT

    10. Januar 2021 um 20:59 Uhr

  • Der Code wird wörtlich mit einem aktualisierten Recaptcha-Schlüssel ausgeführt. Wenn das Formular gesendet wird, führt es die native HTML5-Validierung durch (was ein Plus ist). Es erfasst dann die Werte, z. B. den Namen. Es gibt jedoch kein Token in der verborgenen Eingabe zurück. Es ist leer. Der Grund für die Verwendung von Ereignis-Listenern liegt darin, dass Inline-Klickereignisse durch Inhaltssicherheitsrichtlinien blockiert werden.

    – Motiviert

    10. Januar 2021 um 21:59 Uhr

  • Ich bin kein CSP-Experte. Viele Fragen – aber nicht der Platz in diesen Kommentaren. : P Es klingt wie eine vernünftige Problemumgehung für Ihre Situation. Es gibt so viele Orte, an denen die Änderung schief gehen könnte, insbesondere in der Umgebung $event. Kommt es immer noch wie erwartet durch? Wird aus dem Token erstellt execute Methode? Wird der Token-Wert an das richtige Formular angehängt? Wenn Sie einen Codepen oder ähnliches erstellen, könnte ich beim Debuggen helfen.

    – PigBoT

    11. Januar 2021 um 15:28 Uhr

  • Ich bin mir nicht sicher, ob Codepen oder etwas Ähnliches die Möglichkeit hat, eine CSP-Richtlinie zu implementieren, da dies in der Regel serverseitig ist. Teilen Sie gerne die Inhaltssicherheitsrichtlinie, wenn Sie möchten. Meinst du, es kommt beim Laden durch? Wenn ja, nein, es ist kein Token geladen. Auch beim Absenden des Formulars wird kein Token generiert. Der verborgene Wert ist leer.

    – Motiviert

    11. Januar 2021 um 21:34 Uhr

Ich wollte das gleiche Verhalten, aber mit dem neuen Recaptcha, dem unsichtbaren. Nachdem ich mir etwas Code angeschaut und einige Sachen getestet hatte, kam ich dazu. Der Hauptunterschied besteht darin, dass dies verwendet auch die Standard-Browser-Validierung:

var contact_form;
$(function() {
    contact_form = $('#contact-form');
    contact_form.submit(function (event) {
        if ( ! contact_form.data('passed')) {
            event.preventDefault();
            grecaptcha.execute();
        }
    });
});
function sendContactForm(token) {
    contact_form.data('passed', true);
    contact_form.submit();
}

Es speichert im Grunde das jquery-Formularobjekt in einer globalen Variablen, einschließlich der verwendeten sendContactForm als Callback, aber wenn es von recaptcha aufgerufen wird, setzt es eine Datenvariable namens passed, wodurch das Formular nicht verhindert werden kann. Es ist genau das gleiche Verhalten wie recaptcha normalerweise tun würde, aber mit dieser Bedingung.

Aktualisieren: Ein erneuter Blick auf meinen Code erinnert mich daran, dass es wahrscheinlich einen Weg braucht, um die übergebenen Daten wiederherzustellen false nach der Ausführung von grecaptcha. Berücksichtigen Sie das, wenn Sie dies implementieren.

  • genau der gleiche fluss

    – Julio Guerra

    14. März 2017 um 22:02 Uhr

  • Nein, wenn ich mich gut erinnere, verwendet Ihre obige Antwort keine Standardeinstellungen für die Browservalidierung, meine jedoch. Erwägen Sie, beide zu testen, bevor Sie -1 verlassen. Danke.

    – giovannipds

    9. Juni 2017 um 18:22 Uhr

1445880cookie-checkWie kann ich die HTML-Formularvalidierung vor der reCAPTCHA-Validierung verarbeiten?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy