42 votes

Comment vérifier la réponse Google Recaptcha V3?

Comment intégrer Google reCAPTCHA Version 3 en Client Side et Server Side (php). Le code suivant est utilisé pour afficher reCAPTCHA mais cela ne fonctionne pas bien. Comment faire cette intégration.

    grecaptcha.ready(function() {
      grecaptcha.execute('XXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', {
        action: 'action_name'
      });
    });

Verify.php

success):

             print_r("Working Fine"); exit;
        else:
             print_r("No valid Key"); exit;
        endif;
    } else {
        print_r("Not Working Captcha"); exit;
    }

?>

34 votes

Vous ne devriez pas mettre votre clé secrète dans une question publique sur SO. Si ce n'est pas déjà fait, je recommanderais d'en générer une nouvelle maintenant que vous l'avez partagée avec le monde.

24voto

wkille Points 151

Un exemple simple d'un formulaire de contact vérifié par Google reCAPTCHA v3 avec du JavaScript et du PHP purs.

tldr ; passez au code en bas.

Documents pertinents sur le reCAPTCHA, etc :

(Si Google vous écoute, nous aimons votre travail et il serait merveilleux d'avoir des exemples plus élaborés liés aux pages ci-dessus, s'il vous plaît).

Vue d'ensemble :

  1. Obtenir des clés de Google
  2. Charger recaptcha/api.js dans l'en-tête du html
  3. Détourner la soumission du formulaire avec JavaScript et à ce moment-là, obtenir un jeton de Google.
  4. Soumettez le formulaire avec le jeton à votre serveur
  5. Faites une demande à Google à partir du backend de votre site web pour vérifier la soumission du formulaire
  6. Interpréter la réponse et procéder si nécessaire

Il est important de noter : le paramètre de réponse "success" indique seulement si le captcha a été évalué avec succès ou non, il n'indique pas si la soumission était susceptible d'être un spam ou non.

Le paramètre "score" est le résultat que vous devez connaître. Plus le score est élevé (un nombre compris entre 0 et 1), plus il est probable qu'une soumission soit authentique, et c'est à vous de déterminer le seuil (par exemple 0,5) à accepter.

En détail :

Ajoutez la ligne suivante à l'en-tête de votre HTML pour charger le code recaptcha api.js :

<script src="https://www.google.com/recaptcha/api.js?render=$reCAPTCHA_site_key"></script>

(où $reCAPTCHA_site_key est votre 'clé de site' publique, que j'ai sauvegardée dans un fichier 'config.php').

Vous devez soumettre un jeton (reçu de Google et unique pour chaque soumission de formulaire) à votre serveur. Je pense que le plus simple est de l'envoyer via POST avec le reste des données du formulaire. À cette fin, j'inclus un champ caché dans le formulaire comme suit :

<form id="contactForm" method="post" action="contact">
    <!-- other form inputs -->
    <input type="hidden" id="gRecaptchaResponse" name="gRecaptchaResponse">
    <input type="submit" name="contact_submit" value="Send message">
</form>

(Nb. "contact" est contact.php, mais j'ai 'réécrit' l'url avec .htaccess)

Maintenant nous devons détourner la soumission du formulaire par défaut pour générer le jeton. Nous pourrions générer le jeton au chargement de la page, mais étant donné que le jeton n'est valide que pendant deux minutes (si je me fie à l'exemple de l https://developers.google.com/recaptcha/docs/verify correctement), je pense qu'il est préférable de le récupérer au moment où il faut l'envoyer au serveur de votre site.

À cette fin, j'ai ajouté le texte suivant juste après la balise de fermeture du formulaire :

<script>
    contactForm.addEventListener('submit', event => {
        event.preventDefault()
        validate(contactForm)
    });
</script>

J'ai mis le validate(form) juste avant la balise de fermeture du corps :

function validate(form) {
    //perform optional error checking on form. If no errors then request a token and put it into the hidden field
    getRecaptchaToken(form)
}

//some other (optional) form validation functions

function getRecaptchaToken(form) {
    grecaptcha.ready(function() {
        grecaptcha.execute($reCAPTCHA_site_key, {action: 'contactForm'}).then(function(token) {
            gRecaptchaResponse.value = token //set the value of the hidden field
            form.submit() //submit the form
        });
    });
}

Notes :

  • $reCAPTCHA_site_key est votre clé publique de site
  • action: 'contactForm' identifie la soumission de ce formulaire particulier dans le tableau de bord reCAPTCHA de Google, et la confirmation qu'il est conforme aux attentes dans le backend est une étape de sécurité supplémentaire recommandée. de sécurité

Dans le fichier PHP principal, lorsque la soumission du formulaire est reçue :

//get the IP address of the origin of the submission
$ip = $_SERVER['REMOTE_ADDR'];

//construct the url to send your private Secret Key, token and (optionally) IP address of the form submitter to Google to get a spam rating for the submission (I've saved '$reCAPTCHA_secret_key' in config.php)
$url =  'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($reCAPTCHA_secret_key) . '&response=' . urlencode($g_recaptcha_response) . '&remoteip=' . urlencode($ip);

//save the response, e.g. print_r($response) prints { "success": true, "challenge_ts": "2019-07-24T11:19:07Z", "hostname": "your-website-domain.co.uk", "score": 0.9, "action": "contactForm" }
$response = file_get_contents($url);

//decode the response, e.g. print_r($responseKeys) prints Array ( [success] => 1 [challenge_ts] => 2019-07-24T11:19:07Z [hostname] => your-website-domain.co.uk [score] => 0.9 [action] => contactForm )
$responseKeys = json_decode($response, true);

//check if the test was done OK, if the action name is correct and if the score is above your chosen threshold (again, I've saved '$g_recaptcha_allowable_score' in config.php)
if ($responseKeys["success"] && $responseKeys["action"] == 'contactForm') {
    if ($responseKeys["score"] >= $g_recaptcha_allowable_score) {
        //send email with contact form submission data to site owner/ submit to database/ etc
        //redirect to confirmation page or whatever you need to do
    } elseif ($responseKeys["score"] < $g_recaptcha_allowable_score) {
        //failed spam test. Offer the visitor the option to try again or use an alternative method of contact.
    }
} elseif($responseKeys["error-codes"]) { //optional
    //handle errors. See notes below for possible error codes
    //personally I'm probably going to handle errors in much the same way by sending myself a the error code for debugging and offering the visitor the option to try again or use an alternative method of contact
} else {
    //unkown screw up. Again, offer the visitor the option to try again or use an alternative method of contact.
}

Notes :

  • Voici les données qui figureront dans la réponse de Google (renvoyées sous la forme d'un objet JSON) :

    { "success": true|false, // whether this request was a valid reCAPTCHA token for your site "score": number // the score for this request (0.0 - 1.0) "action": string // the action name for this request (important to verify) "challenge_ts": timestamp, // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ) "hostname": string, // the hostname of the site where the reCAPTCHA was solved "error-codes": [...] // optional }

  • Voici les codes d'erreur possibles :

    • missing-input-secret : Le paramètre secret est manquant.
    • invalid-input-secret : Le paramètre secret est invalide ou malformé.
    • missing-input-response : Le paramètre de réponse est manquant.
    • invalid-input-response : Le paramètre de réponse est invalide ou malformé.
    • bad-request : La demande est invalide ou malformée.
    • timeout-or-duplicate : La réponse n'est plus valide ; elle est soit trop ancienne, soit déjà utilisée. trop ancienne ou a déjà été utilisée.

Tout mettre en place :

contact.php

<?php  //contact.php

    require_once('config.php');

    //do server-side validation of other form fields

    if (/*form has been submitted and has passed server-side validation of the other form fields*/) {
        $ip = $_SERVER['REMOTE_ADDR'];
        $url =  'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($reCAPTCHA_secret_key) . '&response=' . urlencode($g_recaptcha_response) . '&remoteip=' . urlencode($ip);
        $response = file_get_contents($url);
        $responseKeys = json_decode($response, true);

        if ($responseKeys["success"] && $responseKeys["action"] == 'contactForm') {
            if ($responseKeys["score"] >= $g_recaptcha_allowable_score) {
                //send email with contact form submission data to site owner/ submit to database/ etc
                //redirect to confirmation page or whatever you need to do
            } elseif ($responseKeys["score"] < $g_recaptcha_allowable_score) {
                //failed spam test. Offer the visitor the option to try again or use an alternative method of contact.
            }
        } elseif($responseKeys["error-codes"]) { //optional
            //handle errors. See notes below for possible error codes
            //(I handle errors by sending myself an email with the error code for debugging and offering the visitor the option to try again or use an alternative method of contact)
        } else {
            //unkown screw up. Again, offer the visitor the option to try again or use an alternative method of contact.
        }

        exit;

    } else { //(re)display the page with the form

        echo <<<_END

            <!DOCTYPE html>
            <html lang="en">
                <head>
                    <title>Contact | Your website</title>
                    <link rel="stylesheet" href="css/style.css">
                    <script src="https://www.google.com/recaptcha/api.js?render=$reCAPTCHA_site_key"></script>
                </head>
                <body>

                    <!-- header etc -->

                    <form id="contactForm" method="post" action="contact">
                        //other form inputs
                        <input type="hidden" id="gRecaptchaResponse" name="gRecaptchaResponse">
                        <input type="submit" name="contact_submit" value="Send message">
                    </form>
                    <script>
                        contactForm.addEventListener('submit', event => {
                            event.preventDefault()
                            validate(contactForm)
                        });
                    </script>

                    <!-- footer etc -->

                    <script>
                        function validate(form) {
                            //perform optional client-side error checking of the form. If no errors are found then request a token and put it into the hidden field. Finally submit the form.
                            getRecaptchaToken(form)
                        }

                        //some (optional) form field validation functions

                        function getRecaptchaToken(form) {
                            grecaptcha.ready(function() {
                                grecaptcha.execute($reCAPTCHA_site_key, {action: 'contactForm'}).then(function(token) {
                                    gRecaptchaResponse.value = token
                                    form.submit()
                                });
                            });
                        }
                    </script>
                </body>
            </html>

_END;

config.php

<?php //config.php

//other site settings

// Google reCAPTCHA v3 keys
// For reducing spam contact form submissions

// Site key (public)
$reCAPTCHA_site_key = 'N0t-a-real-0N3_JHbnbUJ-BLAHBLAH_Blahblah';

// Secret key
$reCAPTCHA_secret_key = 'N0t-a-real-0N3_i77tyYGH7Ty6UfG-blah';

// Min score returned from reCAPTCHA to allow form submission
$g_recaptcha_allowable_score = 0.5; //Number between 0 and 1. You choose this. Setting a number closer to 0 will let through more spam, closer to 1 and you may start to block valid submissions.

0 votes

grecaptcha.ready s'exécute si la bibliothèque de captcha est chargée. Donc votre code ne l'exécutera pas.

0 votes

@Adam Il semblait que ça marche bien pour moi. J'ai regardé votre question-réponse à stackoverflow.com/questions/60067216/… et la seule différence que je vois est que nous avons fait les choses dans un ordre différent ; je 'prevent default' en dehors de grecaptcha.ready et vous le faites à l'intérieur-?

0 votes

"action": chaîne // Le nom de l'action pour cette demande (important à vérifier) -- est-ce que quelqu'un sait pourquoi c'est si important, comment cela pourrait éventuellement être différent de ce que nous avons envoyé et ce que cela signifie et que faire si ce n'est pas le cas ?

17voto

Bob Points 151

Essayez ceci.

  grecaptcha.ready(function() {
   grecaptcha.execute('YOUR_SITE_KEY', {action: 'MyForm'})
   .then(function(token) {
    console.log(token)
    document.getElementById('g-recaptcha-response').value =    token;
   }); 
  });

4 votes

Vous ne devez pas montrer le site secret côté client. C'est une faute de frappe, utilisez la clé du site à la place du secret du site. (emplacement du secret du site en backend :))

16voto

bsbak Points 611
    // when form is submit
    $('form').submit(function() { 
        // we stoped it
        event.preventDefault();
        // needs for recaptacha ready
        grecaptcha.ready(function() {
            // do request for recaptcha token
            // response is promise with passed token
            grecaptcha.execute('6Le7-FkUAAAAADDSsTVBvpoUB5MkesNKgPVemFf-UD', {action: 'create_comment'}).then(function(token) {
                // add token to form
                $('form').prepend('<input type="hidden" name="token" value="' + token + '">');
                $('form').prepend('<input type="hidden" name="action" value="create_comment">');
                // submit form now
                $('form').unbind('submit').submit();
            });;
        });
    });

php

$token = $_POST['token'];
$secret = 'votre secret';
$action = $_POST['action'];
// maintenant vous devez faire une requête POST au serveur Google ReCAPTCHA.
// url: https://www.google.com/recaptcha/api/siteverify.
// avec les données secret:$secret et response:$token 

À ce stade du code, vous devrez effectuer une requête POST à ReCAPTCHA pour vérifier le jeton, comme documenté ici: https://www.google.com/recaptcha/api/siteverify. La réponse sera un objet JSON avec le champ "success" (true/false) et "action" pour la comparaison (==) et le score (nombre de 0.0 à 1.0)

https://developers.google.com/recaptcha/docs/v3#api-response.

Vous pouvez également spécifier le nom de l'action pour chaque requête (create_post, update_post, create_comment ...)

3 votes

$jeton = $_POST['jeton']; $action = $_POST['action']; if(isset($jeton) && !empty($jeton)){ //obtenir les données de réponse de vérification $reponseVerification = file_get_contents( 'google.com/recaptcha/api/…'); $donneesReponse = json_decode($reponseVerification); } if($responseData->success) { //Captcha est bon }

1 votes

Cela ne semble pas fonctionner sur la V3 et semble être un mélange de méthodes v2 et v3.

1 votes

@Dave si vous connaissez une meilleure méthode pour implémenter v3, veuillez fournir une réponse

2voto

Shaikh Shahid Points 831

Voici un code de travail d'exemple avec la démo.

Code côté html

    Google recapcha v3 demo - Codeforgeek

    Google reCAPTHA Demo

       // quand le formulaire est soumis
    $('#comment_form').submit(function() {
        // on le stoppe
        event.preventDefault();
        var email = $('#email').val();
        var comment = $("#comment").val();
        // nécessaire pour la recaptcha ready
        grecaptcha.ready(function() {
            // demande de jeton recaptcha
            // la réponse est une promesse avec un jeton passé
            grecaptcha.execute('put your site key here', {action: 'create_comment'}).then(function(token) {
                // ajouter un jeton au formulaire
                $('#comment_form').prepend('<input type="hidden" name="g-recaptcha-response" value="' + token + '">');
                    $.post("form.php",{email: email, comment: comment, token: token}, function(result) {
                            console.log(result);
                            if(result.success) {
                                    alert('Merci d\'avoir posté un commentaire.')
                            } else {
                                    alert('Vous êtes un spammeur ! Dégagez.')
                            }
                    });
            });;
        });
  });

Code PHP.

Veuillez vérifier le formulaire captcha.';
          exit;
        }
        $secretKey = "put your secret key here";
        $ip = $_SERVER['REMOTE_ADDR'];

        // requête post au serveur

        $url =  'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($secretKey) .  '&response=' . urlencode($captcha);
        $response = file_get_contents($url);
        $responseKeys = json_decode($response,true);
        header('Content-type: application/json');
        if($responseKeys["success"]) {
                echo json_encode(array('success' => 'true'));
        } else {
                echo json_encode(array('success' => 'false'));
        }
?>

Ça fonctionne bien.

Demo: https://demo.codeforgeek.com/recaptcha-v3/

tutoriel: https://codeforgeek.com/2019/02/google-recaptcha-v3-tutorial/

2voto

Giorgio C. Points 31

Je voudrais vous donner un flux de travail complet pour intégrer recaptcha v3 dans une solution ASP.NET Core MVC.

dans votre fichier appsettings.json:

  "RecaptchaSettings": {
    "Uri": "https://www.google.com/recaptcha/api/siteverify",
    "SecretKey": "votre clé privée"
    "SiteKey": "votre clé publique",
    "Version": "v3"
  }

dans votre vue (@razor syntax):

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

        grecaptcha.ready(function () {
            grecaptcha.execute('@Configuration.GetSection("RecaptchaSettings")["SiteKey"]',  { action: 'homepage' })
                .then(function (token) {

                    document.getElementById('g-recaptcha-response').value = token;
                });
        });

et dans votre formulaire mettez ceci:

…

…

Je crée une méthode simple pour le gérer:

public async Task ChallengePassed(string uri, string gRecaptchaResponse, string secret)
        {

            var concUri = uri + "?secret=" + secret + "&response=" + gRecaptchaResponse;

            var request = new HttpRequestMessage(HttpMethod.Get, concUri);
            var res = await _Client.SendAsync(request);

            if (!res.IsSuccessStatusCode)
            {
                return false;
            }

            var data = await res.Content.ReadAsStringAsync();

            dynamic JSONdata = JObject.Parse(data);
            if (JSONdata.success != "true")
            {
                return false;
            }

            return true;
        }

        #endregion

        #region PRIVATE

        #endregion

        #endregion

        #endregion
    }

et simplement je l'ai appelé dans un contrôleur:

 //validation recaptcha

    bool isChallengeOk = await _CaptchaVerify.ChallengePassed(_Configuration.GetValue("RecaptchaSettings:Uri"), Request.Form["g-recaptcha-response"], _Configuration.GetValue("RecaptchaSettings:SecretKey"));

Remarquez que je définis les paramètres d'entrée à partir de l'objet "_Configuration", qui représente une instance d'objet de réglage de configuration dans Startup.cs. Vous pouvez passer manuellement les paramètres d'entrée à la méthode.

Profitez-en

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X