web-dev-qa-db-fra.com

Invisible ReCaptcha avec jQuery ajax

J'essaie d'implémenter la dernière version de ReCaptcha (alias "invisible" ReCaptcha) dans un formulaire à l'aide de jQuery et d'une requête "ajax".
Documentation ReCaptcha: https://developers.google.com/recaptcha/docs/invisible

Ma forme:

<form id="myForm" >
    <input type="email" name="email" /><br />
    <input type="password" name="password" /><br/>
    <!--<input type="submit" value="log in" />-->
    <button class="g-recaptcha" data-sitekey="6LdK..." data-callback="onSubmit">log in</button>
</form>
<div id="status"></div>

Mon javascript (jQuery):

<script>

    function onSubmit(token){
        document.getElementById("myForm").submit();
    }

    $(document).ready(function(){

        $("#myForm").submit(function(event){
            event.preventDefault();
            var datas = $("#myForm").serialize();
            $.ajax({
                type: "POST",
                url: "test.php",
                data: datas,
                dataType: "json",
                    beforeSend: function(){
                        $("#status").html("logging in...");
                    },
                    success: function(response){
                        $("#status").html(response.text);
                        if(response.type=="success"){
                            window.location.replace("/myaccount");
                        }
                    },
                    error: function(){
                        $("#status").html("Failed.");
                    }
            });
        });

    });
</script>

ReCaptcha nécessite de définir un "rappel de données", que je ne suis pas sûr de savoir comment lier avec ma fonction ".submit (function (event)") déjà existante.
Mon astuce "onSubmit ()" n'a pas fonctionné, il ignore le "ajax" et rafraîchit la page.

Comment puis-je envoyer la valeur "g-recaptcha-response" dans ma variable "datas" à POST à test.php?

9
13h50

Voici donc comment je l'ai résolu après avoir approfondi ma recherche dans la documentation d'Invisible reCAPTCHA et appris un peu de jQuery, car je ne connaissais pas très bien JS (des trucs sympas):

Ma balise de tête avec le javascript (et un peu de css pour enlever le mauvais badge Google):

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit&hl=fr" async defer></script>

<style>
    .grecaptcha-badge{
        display:none;
    }
</style>

<script>
    var onloadCallback = function(){
        grecaptcha.render("emplacementRecaptcha",{
            "sitekey": "YOUR_RECAPTCHA_SITEKEY_HERE",
            "badge": "inline",
            "type": "image",
            "size": "invisible",
            "callback": onSubmit
        });
    };
    var onSubmit = function(token){
        var userEmail = $("#userEmail").val();
        var userPassword = $("#userPassword").val();
        var userTfaOtp = $("#userTfaOtp").val();
        $.ajax({
            type: "POST",
            url: location.href,
            data:{
                    userEmail: userEmail,
                    userPassword: userPassword,
                    userTfaOtp: userTfaOtp,
                    userJetonRecaptcha: token
                },
            dataType: "json",
                beforeSend: function(){
                    $("#statutConnexion").html("Traitement de votre requête d'authentification en cours...");
                },
                success: function(response){
                    $("#statutConnexion").html(response.Message);
                    if(response.Victoire){
                        $("#formulaireConnexion").slideUp();
                        window.location.replace("/compte");
                    }
                    else{
                        grecaptcha.reset();
                    }
                },
                error: function(){
                    $("#statutConnexion").html("La communication avec le système d'authentification n'a pas pu être établie. Veuillez réessayer.");
                    grecaptcha.reset();
                }
        });
    };
    function validate(event){
        event.preventDefault();
        $("#statutConnexion").html("Validation de votre épreuve CAPTCHA en cours...");
        grecaptcha.execute();
    }
    function onload(){
        var element = document.getElementById("boutonConnexion");
        element.onclick = validate;
    }
</script>

HTML:

<div id="formulaireConnexion">
    <input type="email" name="userEmail" id="userEmail" placeholder="Courriel" title="Courriel" required="required" /><br />
    <input type="password" name="userPassword" id="userPassword" placeholder="Mot de passe" title="Mot de passe" required="required" /><br/>
    <input type="text" name="userTfaOtp" id="userTfaOtp" placeholder="Double authentification (optionnelle)" autocomplete="off" pattern="[0-9]{6}" title="Six caractères numériques" maxlength="6" /><br />
    <div id="emplacementRecaptcha"></div>
    <button id="boutonConnexion">Connexion</button>
</div>
<div id="statutConnexion"></div>
<script>onload();</script>

Faites-moi savoir si vous avez besoin de l'intégralité de PHP également, car elle ne relève pas de la portée de cette question. Vous aurez probablement besoin de changer "url: location.href" dans le JS ci-dessus car dans mon cas, le script rendant le formulaire HTML et le JS et traitant les vars POST est le même (pas génial, le but du test ). En gros, je vérifie simplement les vars POST, puis je retourne un json du type:

$jsonVictoire = true; // boolean
$jsonMessage = 'anything you want to tell your visitor'; // string

$return = 
    json_encode(
        array(
            'Victoire'=>$jsonVictoire,
            'Message'=>$jsonMessage
        )
    );
die($return);
9
13h50
<script defer>              
function onSubmit(token) {                      
    var f = $("#myForm");

    $.ajax({
        type: "POST",
        url: "test.php",
        data: f.serialize(),
        dataType: "json",
        beforeSend: function(){
            $("#status").html("logging in...");
        },
        success: function(response){
            $("#status").html(response.text);
            if(response.type=="success"){
                window.location.replace("/myaccount");
            } else {
                $("#status").html("Captcha failed.");
            }
        },
        error: function(){
            $("#status").html("Failed.");
        }       
    });
}
</script>

Dans test.php, vous devez vérifier le captcha côté serveur:

<?php
if(isset($_POST['g-recaptcha-response'])) {
    $result = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=[YOUR_SECRET_KEY]&response=$_POST["g-recaptcha-response"]&remoteip=$_SERVER["REMOTE_ADDR"]'), TRUE);

    if($result['success'] == 1) {
        // Captcha ok
    } else {
        // Captcha failed
    }
}
?>
2
dbx