web-dev-qa-db-fra.com

Invisible google Recaptcha et ajax form

J'ai un formulaire ajax:

  <form id="my_form">
    <input type="text" id="field1" />
    <input type="submit" value="submit" />
  </form>

Et le code js:

document.getElementById("my_form").onsubmit = function(e) {
  e.preventDefault();

  var xhr = new XMLHttpRequest();
  //.............. send request to a server

Dans la documentation, il suppose qu'un formulaire est un formulaire normal, pas ajax. Comment dois-je intégrer exactement reCaptcha invisible à mes formulaires ajax? Par exemple:

  <form id="my_form">
    <input type="text" id="field1" />
    <div class="g-recaptcha" data-sitekey="12345" data-callback="????></div>
    <input type="submit" value="submit" />
  </form>

Et, en particulier, que dois-je spécifier pour le gestionnaire de "rappel de données"? Encore une fois, dans la documentation, data-callback soumet un formulaire, mais un formulaire normal, tandis que le mien est ajax. Ai-je besoin d'un "rappel de données"? Ne devrais-je pas plutôt appeler recaptcha dans mon gestionnaire? Comment?

Il y a "render", "getResponse" et "execute". Lequel devrais-je utiliser? Ce n'est pas clair dans la documentation.

13
Kuqa

Je suis d'accord que la documentation de recaptcha "invisible" n'est pas assez complète. J'ai dû passer un peu de temps à creuser à travers des exemples de code et des documentations de recaptcha "visible" avant de comprendre comment travailler avec cela.

Parlons d'abord de l'API recaptcha:

grecaptcha.render(htmlEl, options, inherit) est la méthode API JS de rendu du HTML captcha sur la page. Par défaut, le script recaptcha essaiera de trouver n'importe quel élément avec class="g-recaptcha Et essaiera de s'afficher immédiatement, mais ce comportement peut être remplacé en ajoutant ?render=explicit Paramètre de requête à l'URL src du script recaptcha. Vous pouvez également vouloir rendre le recaptcha html à la demande en utilisant cette api lorsque votre élément recaptcha .g-recaptcha Est attaché au DOM à un moment plus tard que lorsque le script a été chargé. Cette api renvoie une valeur d'ID qui peut être transmise à d'autres méthodes d'api, mais si elle n'est pas transmise, la recherche et la référence de ces api sont d'abord repcaptcha sur la page.

grecaptcha.getResponse(optional_id) renvoie le jeton. Si le jeton est une chaîne vide, cela signifie que l'utilisateur n'a pas encore été validé, c'est-à-dire que l'utilisateur n'a pas terminé le défi captcha.

grecaptcha.execute(optional_id) api déclenche le défi recaptcha à la demande par programmation. Cette API n'est applicable qu'aux recaptcha "invisibles". Les défis de recaptcha visibles sont déclenchés lorsque l'utilisateur clique sur le module recaptcha.

grecaptcha.reset(optional_id) réinitialisera un défi, c'est-à-dire qu'il doit être fait chaque fois que le serveur ne valide pas le jeton avec le serveur api recaptcha (car les jetons sont à usage unique), mais selon votre implémentation, vous pouvez décider de réinitialiser à tout moment .

Maintenant, parlons de rappel de données:

data-callback Est un attribut dans lequel vous pouvez passer un nom de fonction d'espace de nom global, c'est-à-dire une fonction accessible comme fenêtre ['nameOfFunction']. Ce rappel sera appelé chaque fois que l'utilisateur est validé avec succès avec une valeur de jeton que vous finirez par transmettre au serveur. C'est le même jeton qui est retourné par grecaptcha.getResponse() donc techniquement vous n'avez pas du tout besoin de cette fonction. Mais il peut servir de rappel pour vous faire savoir que l'utilisateur a réussi la vérification au cas où vous auriez besoin de mettre à jour l'interface utilisateur ou quelque chose.

Si, pour une raison quelconque, vous ne souhaitez pas que ce rappel soit accessible à partir de l'espace de noms de fenêtre, vous pouvez passer cette méthode dans l'objet options avec la touche callback à grecaptcha.render(). REMARQUE: options.callback Peut prendre une valeur de chaîne qui équivaut à passer l'attribut data-callback En HTML, c'est-à-dire qu'il doit s'agir d'une fonction dans l'espace de noms de fenêtre. Mais options.callback Peut également prendre une valeur de "fonction".


Maintenant, un exemple de code:

[~ # ~] html [~ # ~]

<script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=onScriptLoad" async defer></script>

[~ # ~] js [~ # ~]

window.onScriptLoad = function () {
    // this callback will be called by recaptcah/api.js once its loaded. If we used
   // render=explicit as param in script src, then we can explicitly render reCaptcha at this point

    // element to "render" invisible captcha in
    var htmlEl = document.querySelector('.g-recaptcha');

    // option to captcha
    var captchaOptions = {
      sitekey: '6Lck',
      size: 'invisible',
      // tell reCaptcha which callback to notify when user is successfully verified.
      // if this value is string, then it must be name of function accessible via window['nameOfFunc'], 
      // and passing string is equivalent to specifying data-callback='nameOfFunc', but it can be
      // reference to an actual function
      callback: window.onUserVerified
  };

    // Only for "invisible" type. if true, will read value from html-element's data-* attribute if its not passed via captchaOptions
    var inheritFromDataAttr = true;

    // now render
    recaptchaId = window.grecaptcha.render(htmlEl, captchaOptions, inheritFromDataAttr);
};

// this is assigned from "data-callback" or render()'s "options.callback"
window.onUserVerified = function (token) {
    alert('User Is verified');
    console.log('token=', token);
};


// click handler for form's submit button
function onSubmitBtnClick () {      
  var token =   window.grecaptcha.getResponse(recaptchaId);

  // if no token, mean user is not validated yet
  if (!token) {
     // trigger validation
     window.grecaptcha.execute(recaptchaId);
     return;
  }

  var xhrData = {
    'g-recaptcha-response': token
    // more ajax body/data here
  };

  // proceed with appending more ajax call data to xhrData and then rest of ajax call process
  // var xhr = new XMLHttpRequest();
  // ... ... .... ... ... 
}
30
codneto