6
votes

Comment résoudre le délai d'expiration de Google v3 reCaptcha?

Nous avons un formulaire PHP qui comporte plusieurs onglets et des délais d'expiration sur le reCaptcha. Tout est fait sur une seule page et cela fonctionne parfaitement SI le formulaire est rempli en moins de 3 minutes.

L'idée d'une solution est de déplacer le traitement du formulaire et le reCaptcha vers une page secondaire pour traitement.

Le problème est que la page de formulaire interroge le service google pour reCaptcha et collecte une valeur de jeton dans un champ masqué.

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['recaptcha_response'])) {

// Build POST request:
$recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
$recaptcha_secret = RECAPTCHA_SECRET_KEY;
$recaptcha_response = $_POST['recaptcha_response'];
$remoteip = $_SERVER['REMOTE_ADDR'];

// Make and decode POST request:
$recaptcha = file_get_contents($recaptcha_url . '?secret=' . $recaptcha_secret . '&response=' . $recaptcha_response. '&remoteip='.$remoteip);
$recaptcha = json_decode($recaptcha);

// Take action based on the score returned:
if ($recaptcha->score >= 0.5) {

Le problème est de savoir comment demander ce jeton sur le serveur page de traitement latérale? Voici le code utilisé sur la page du formulaire côté client. Je dois en quelque sorte régénérer la valeur du jeton à appliquer comme:

$ recaptcha_response

Voici la version de travail sur la page du formulaire. Il est facile de supprimer l'exigence relative à la publication du jeton de la page de formulaire, mais vous ne savez pas comment régénérer le jeton à utiliser sur la page côté serveur.

<input type="hidden" name="recaptcha_response" id="recaptchaResponse">

MODIFIER POUR AJOUTER: Est-ce que l'initialisation du reCaptcha jusqu'à la soumission retarderait le problème de synchronisation car cela semble être une option:

https://developers.google.com/recaptcha/docs/v3

"2. Appelez grecaptcha.execute sur une action ou lors du chargement de la page" p >


4 commentaires

Votre côté serveur semble ok etc., mais le côté client nécessitera une autre exécution de grecaptcha.ready (function () {grecaptcha.execute (...);})


Vous dites que la solution est de ne pas passer à une page secondaire (qui fonctionne maintenant si <~ 3 minutes) mais de réexécuter l'envoi et la réception du jeton avant de publier le Soumettre?


cela dépend du moment où vous avez besoin des informations captcha, si vous en avez besoin et qu'elles ont expiré - le seul moyen de les récupérer est de demander au client (navigateur) de demander un jeton - et au serveur de le vérifier. personnellement, une fois que j'ai vérifié le client - je n'ai pas besoin de le revérifier - même après 10 minutes.


Donc, plutôt que sur Soumettre, vérifiez le client lors du chargement de la page, ce qui supprime la possibilité de délai d'attente. C'est un autre concept et c'est logique!


4 Réponses :


4
votes
<script type="text/javascript">
function grecaptcha_execute(){
    grecaptcha.execute('RECAPTCHA_SITE_KEY', {action: 'homepage'}).then(function(token) {
        document.getElementById('recaptchaResponse').value=token;
    });
}
grecaptcha.ready(function() {
    grecaptcha_execute();
});
</script>

<?php
if ($recaptcha->success) {
    echo '<p style="color: #0a860a;">CAPTCHA was completed successfully!</p>';
}else{
    $error_codes = 'error-codes';
    if (isset($Retorno->$error_codes) && in_array("timeout-or-duplicate", $Retorno->$error_codes)) {
        $captcha_msg = "The verification expired due to timeout, please try again.";
    ?>
    <script>grecaptcha_execute();</script>
    <?php
    } else {
        $captcha_msg = "Check to make sure your keys match the registered domain and are in the correct locations.<br> You may also want to doublecheck your code for typos or syntax errors.";
    }
    echo '<p style="color: #f80808;">reCAPTCHA error: ' . $captcha_msg . '</p>';
}
?>

0 commentaires

12
votes

Si vous ne souhaitez pas trop changer votre code, une autre approche serait d'envelopper le JavaScript reCaptcha dans une fonction nommée, de configurer un intervalle et d'interroger cette fonction en invitant reCaptcha à ajouter un nouveau jeton à votre élément de formulaire chaque trois minutes:

function getReCaptcha(){
    grecaptcha.ready(function() {
       ...
     });
 }

 getReCaptcha();  // This is the initial call
 setInterval(function(){getReCaptcha();}, 150000);


0 commentaires

3
votes

Nous avons également rencontré ce problème récemment. J'ai trouvé cette solution sur GitHub et cela fonctionne bien pour nous.

Cela présente l'avantage de ne demander un jeton que lorsque l'utilisateur interagit avec la page (par exemple en soumettant un formulaire) au lieu de devoir continuer à en demander un.

<script>
  grecaptcha.ready(function() {
      document.getElementById('contactform').addEventListener("submit", function(event) {

        event.preventDefault();

        grecaptcha.execute('mykey', {action: 'homepage'}).then(function(token) {
           document.getElementById("googletoken").value = token; 
           document.getElementById('contactform').submit();
        });        
      }, false);

  });
</script>

p>


4 commentaires

Merci, je vais essayer votre méthode la prochaine fois que nous coderons quelque chose de similaire.


J'ai juste eu le même problème et implémenté la méthode en utilisant une fonction nommée et en écoutant "soumettre" et cela a fonctionné parfaitement.


rifton007 a commenté le 13 février @ iwasherefirst2 La solution n'est pas parfaite. Parce que, lorsque nous demandons le jeton juste avant l'envoi. Le formulaire a besoin d'attendre quelques secondes pour recevoir le jeton et envoyer avec les données.


C'est vrai, donc dans ce cas, vous pouvez simplement afficher une sorte d'indicateur "fonctionnel" juste après event.preventDefault (); afin que l'utilisateur sache que le formulaire est soumis, ce qui devrait prendre en charge la plupart préoccupations.



1
votes

Chargez l'API reCaptcha js et Jquery (si vous utilisez le code jquery):

<form method="POST">
    <label class="label">Name</label>
    <input type="text" name="name" class="input" placeholder="Name" required>
    <button type="submit" name="submit" class="button is-link">Send Message</button>
    <input type="hidden" name="recaptcha_response" id="recaptchaResponse">
</form>

reCaptcha Render Javascript:

<?php 
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit'])) {
        if(isset($_POST['recaptcha_response']) && !empty($_POST['recaptcha_response'])){
            $recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
            $recaptcha_secret = 'SECRET_KEY';
            $recaptcha_response = $_POST['recaptcha_response'];
            $response = file_get_contents($recaptcha_url . '?secret=' . $recaptcha_secret . '&response=' . $recaptcha_response);
            $recaptcha = json_decode($response);
            if ($recaptcha->success == true && $recaptcha->score >= 0.5) {
                echo $response;
                echo '<br>Form Submitted Successfully';
            } else { 
                echo $response;
                echo '<br>reCaptcha varification failed';
            }
        }else {
            echo 'reCaptcha is empty';
        } 
    }
?>

Varifier le site:

  <script type="text/javascript">
     $(document).ready(function(){
        setInterval(function(){
        grecaptcha.ready(function() {
            grecaptcha.execute('SITE_KEY', {action: 'home'}).then(function(token) {
                $('#recaptchaResponse').val(token);
            });
        });
        }, 3000); //you can set timeout for expired.
     });
     
  </script>

Formulaire HTML:

<script src="https://www.google.com/recaptcha/api.js?render=SITE_KEY"></script>
<script  src="https://code.jquery.com/jquery-3.4.1.min.js"></script>


0 commentaires