web-dev-qa-db-fra.com

Nouveau plugin reCaptcha avec jQuery Validation

J'ai beaucoup cherché mais je ne sais pas comment valider le nouveau reCaptcha , avant de soumettre le formulaire, ainsi que la fonction de validation de plugin de validation jQuery .

Je veux dire quelque chose comme ça:

    $.validator.addMethod('reCaptchaMethod', function (value, element, param) {
            if (grecaptcha.getResponse() == ''){
                return false;
            } else {
                // I would like also to check server side if the recaptcha response is good
                return true
            }
        }, 'You must complete the antispam verification');


    $("#form").validate({
            rules: {
                name: {
                    required: true,
                    minlength: 2
                },
                email: {
                    required: true,
                    email: true
                },
                reCaptcha: {
                    reCaptchaMethod: true   
                }
            },
            messages: {
                name: "Please fill your name",
                email: "Please use a valid email address"
            },
            submitHandler : function () {
                        $.ajax({
                            type : "POST",
                            url : "sendmail.php",
                            data : $('#form').serialize(),
                            success : function (data) {
                                $('#message').html(data);
                            }
                        });
                    }


        });

En quelques mots, je voudrais vérifier côté serveur, avec la méthode distante , si l'utilisateur a passé la validation recaptcha AVANT de soumettre le formulaire, ainsi que les autres règles de validation.

Je suis en mesure de vérifier la recaptcha APRÈS l'envoi (sur sendmail.php), mais il serait préférable d'avoir la réponse de validation recaptcha avec la validation d'autres champs.

La raison principale en est une meilleure expérience utilisateur, tous les champs étant vérifiés en même temps.

J'ai réussi à réaliser quelque chose en déplaçant le chèque à l'intérieur de submitHandler:

            submitHandler : function () {
                  if (grecaptcha.getResponse() == ''){
                      // if error I post a message in a div
                      $( '#reCaptchaError' ).html( '<p>Please verify youare human</p>' );

                  } else {

                        $.ajax({
                            type : "POST",
                            url : "sendmail.php",
                            data : $('#form').serialize(),
                            success : function (data) {
                                $('#message').html(data);
                            }
                        });
                    }

             }

Mais je n'aime pas pour 2 raisons: 1) Je vérifie juste si le recaptcha a été rempli, pas s'il est valide. 2) L'utilisateur se sent comme une vérification en 2 étapes.

Dans cette réponse ils disent que cela peut être fait en rendant le Recaptcha sur un rappel, pour spécifier un appel de fonction sur une réponse CAPTCHA réussie.

J'ai essayé d'implémenter cela, mais je n'ai pas pu utiliser cette solution dans une règle de la fonction validate ().

Tout indice est le bienvenu!

35
bluantinoo

Je sais que cette question est un peu dépassée, mais j'avais le même problème et je viens de trouver la solution. Vous pouvez faire cela en ajoutant un champ caché à côté du reCaptcha div, comme:

<div class="g-recaptcha" data-sitekey="{YOUR-SITE-KEY-HERE}"></div>
<input type="hidden" class="hiddenRecaptcha required" name="hiddenRecaptcha" id="hiddenRecaptcha">

puis dans votre javascript:

$("#form").validate({
        ignore: ".ignore",
        rules: {
            name: {
                required: true,
                minlength: 2
            },
            email: {
                required: true,
                email: true
            },
            hiddenRecaptcha: {
                required: function () {
                    if (grecaptcha.getResponse() == '') {
                        return true;
                    } else {
                        return false;
                    }
                }
            }
        },(...rest of your code)

AVIS QUE VOUS DEVEZ AVOIR le ignore: ".ignore" dans votre code car jquery.validate ignore les champs cachés par défaut, sans les valider.

Si vous souhaitez supprimer le message d'erreur lors de la validation reCapcha, ajoutez un rappel de données à l'élément reCapcha.

<div class="g-recaptcha" data-sitekey="{YOUR-SITE-KEY-HERE}" data-callback="recaptchaCallback"></div>

Et puis dans votre fichier js, ajoutez

function recaptchaCallback() {
  $('#hiddenRecaptcha').valid();
};
76
FabioG

Vous pouvez également empêcher le formulaire de soumettre dans le submitHandler

$("#loginForm").validate({
rules: {
    username: {
        required: true,
        minlength: 6
    },
    password: {
        required: true,
    },
},
submitHandler: function(form) {
    if (grecaptcha.getResponse()) {
        form.submit();
    } else {
        alert('Please confirm captcha to proceed')
    }
}
});
11
Ranjith Singhu

J'ai trouvé votre solution intéressante (@FabioG).

Mais, je l'ai modifié pour l'utiliser un peu par moi-même et je suis prêt à partager le code pour que d'autres l'utilisent.

Je travaillais sur un formulaire interactif, qui a validé au fur et à mesure que vous complétiez les étapes.

Il a été utilisé pour commander de la nourriture. Ainsi, le formulaire nécessite la vérification et l'activation du bouton d'enregistrement et il utilise le dernier reCaptcha à ce jour (05/12/2016).

En outre, ce code gère la vérification expirée de reCaptcha, côté serveur, via ajax (pâte non incluse - si quelqu'un en a besoin, n'hésitez pas à commenter ma réponse et je la modifierai en conséquence).

Commençons.

Le code HTML:

<form id="registerForm" method="get" action="">
<fieldset class="step-1">
<h4>Step One:</h4>
<span class="clock">Register under one minute!</span>
<label for="email-register" class="label">E-mail*</label>
<input id="email-register" name="email-register" type="email" value="" autocomplete="off"/>

<label for="password-register" class="label">Password*</label>
<input id="password-register" name="password-register" type="password" value="" autocomplete="off"/>

<div class="g-recaptcha" data-sitekey="6LeS4O8SAAAAALWqAVWnlcB6TDeIjDDAqoWuoyo9" data-callback="recaptchaCallback" data-expired-callback="recaptchaExpired" style="margin-top: 3rem;"></div>
<input id="hidden-grecaptcha" name="hidden-grecaptcha" type="text" style="opacity: 0; position: absolute; top: 0; left: 0; height: 1px; width: 1px;"/>
</div>
</fieldset>
<fieldset class="step-2">
<h4>Step two:</h4>
<span class="notice">All fields with a sign are required!*</span>
<label for="first-name" class="label">First Name*</label>
<input name="first-name" id="first-name" type="text" value="" />

<label for="last-name" class="label">Last Name*</label>
<input name="last-name" id="last-name" type="text" value="" />

<label for="address" class="label">Address*</label> 
<input name="address" id="address" type="text" value=""/>

<label for="entrance" class="label">Entrance</label>    
<input name="entrance" id="entrance" type="text" value=""/>

<label for="apartment-number" class="label">Apartment #</label>
<input name="apartment-number" id="apartment-number" type="text" value="" />

<label for="inter-phone" class="label">Interphone</label>           
<input name="inter-phone" id="inter-phone" type="text" value=""/>

<label for="telephone" class="label">Mobile Number*</label>
<input name="telephone" id="telephone" type="text" value="" />

<label for="special-instructions" class="label">Special Instructions</label>    
<textarea name="special-instructions" id="special-instructions"></textarea>
<div>
</fieldset>
<button class="button-register" disabled>Register</button>
</form>

Comme vous pouvez le constater, le bouton de soumission (".button-register") est initialement désactivé.

Vous ne pouvez l'activer qu'en remplissant les champs obligatoires (*).

S'il vous plaît, gardez à l'esprit que je n'ai inclus aucun CSS. Le formulaire est à un minimum d'ours et est juste pour des buts éducatifs.

Peu de choses diffèrent de @FabioG, répondez-y:

Il n'est pas nécessaire de cacher l'élément ou d'utiliser le ".ignore". Je l'ai caché avec CSS en ligne.

Il existe un rappel de réponse en cas de succès de reCaptcha et de reCaptcha expiré.

Ainsi, si votre reCaptcha expire lors du remplissage du formulaire, il sera invalide et le bouton sera désactivé à nouveau.

De plus, le formulaire utilise un champ de saisie (le champ de saisie masqué) pour transmettre les informations à AJAX (plus tard, PHP) et le vérifier côté serveur (Il s’agit d’un risque potentiel pour la sécurité, je l’ai couvert davantage à la fin. du texte).

Passons à JavaScript/jQuery.

JavaScript/jQuery:

function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};
function recaptchaCallback() {
    var response = grecaptcha.getResponse(),
        $button = jQuery(".button-register");
    jQuery("#hidden-grecaptcha").val(response);
    console.log(jQuery("#registerForm").valid());
    if (jQuery("#registerForm").valid()) {
        $button.attr("disabled", false);
    }
    else {
        $button.attr("disabled", "disabled");
    }
}

function recaptchaExpired() {
    var $button = jQuery(".button-register");
    jQuery("#hidden-grecaptcha").val("");
    var $button = jQuery(".button-register");
    if (jQuery("#registerForm").valid()) {
        $button.attr("disabled", false);
    }
    else {
        $button.attr("disabled", "disabled");
    }
}
function submitRegister() {
  //ajax stuff
}
(function ($, root, undefined) {
    $(function () {
        'use strict';
        jQuery("#registerForm").find("input").on("keyup", debounce(function() {
          var $button = jQuery(".button-register");
          if (jQuery("#registerForm").valid()) {
            $button.attr("disabled", false);
          }
          else {
            $button.attr("disabled", "disabled");
          }
        }, 1000));
        jQuery("#registerForm").validate({
          rules: {
            "email-register": {
              required: true,
              email: true
            },
            "password-register": {
              required: true,
              minlength: "6"
            },
            "first-name": "required",
            "last-name": "required",
            address: "required",
            telephone: "required",
            "hidden-grecaptcha": {
              required: true,
              minlength: "255"
            }
          },
          messages: {
            "email-register": "Enter valid e-mail address",
            "password-register": {
              required: "Enter valid password",
              minlength: "Password must be bigger then 6 chars!"
            },
            "first-name": "Required!",
            "last-name": "Required!",
            address: "Required!",
            telephone: "Required!"
          },
          submitHandler: submitRegister
        });
    }); 
})(jQuery, this);

Comme vous pouvez le voir ici, il existe quelques fonctions: recaptchaCallback () et recaptchaExpired ().

recaptchaCallback () intégré via l'attribut data data-callback, utilise le grecaptcha.getResponse () pour voir si le reCaptcha est validé, le cas échéant, il entre le jeton dans le champ de saisie masqué et demande une nouvelle validation par le jQuery (" #registerForm) .validate ();.

Cependant, si le reCaptcha expire entre-temps, il utilisera la fonction attribuée dans le "rappel de données expirées" pour supprimer le jeton du champ de saisie et demander à nouveau une nouvelle validation qui échouera car le champ est vide. Ceci est réalisé avec la fonction recaptchaExpired () .

Plus loin dans le code, vous pouvez voir que nous avons ajouté une fonction jQuery keyup, afin de vérifier la revalidation et de voir si l'utilisateur a transmis les informations requises aux champs de saisie. Si les informations et le champ valident avec succès, la fonction keyup activera le bouton Enregistrer .

De plus, j'ai utilisé un script anti-rebond (tnx, David Walsh) sur keyup . Donc, cela ne provoque pas de décalage du navigateur. Depuis, il y aurait beaucoup de dactylographie.

Mais gardez à l’esprit que si un utilisateur décide de contourner le reCaptcha, il peut toujours entrer une chaîne longue de "255" dans le champ de saisie. Mais, j’ai fait un pas de plus et fait un AJAX côté serveur de vérification pour confirmer le reCaptcha. Dough, je ne l’ai pas inclus dans la réponse.

Je pense que ce code est une amélioration marginale par rapport à la réponse précédente. Si vous avez des questions ou avez besoin du code AJAX/PHP, n'hésitez pas à commenter. Je le fournirai quand je peux.

Voici également le code: reCaptcha avec jQuery.validation

Vous pouvez trouver toutes les informations concernant les attributs de données et les fonctions reCatpcha dans leur api ici: API reCaptcha

J'espère que ça a aidé quelqu'un!

Cordialement,

2
steviss

J'ai eu du mal avec celui-ci aujourd'hui et j'ai fini par aller avec:

<form onsubmit="return $(this).valid() && grecaptcha.getResponse() != ''">

Ce qui semble être le moyen le plus simple de le faire. Quelqu'un est forcé de se plaindre de mettre js en ligne comme ça, mais ça me va.

0
pguardiario