web-dev-qa-db-ja.com

目に見えないGoogle Recaptchaとajaxフォーム

私はajaxフォームを持っています:

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

そして、jsコード:

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

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

ドキュメントでは、フォームはajaxではなく通常のフォームであると想定しています。目に見えないreCaptchaをajaxフォームにどの程度正確に統合する必要がありますか?例えば:

  <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>

そして、特に、「データコールバック」ハンドラーに何を指定する必要がありますか?繰り返しになりますが、ドキュメントでは、データコールバックはフォームを送信しますが、通常のフォームを送信しますが、私の場合はajaxです。 「データコールバック」はまったく必要ですか?代わりにハンドラー内でrecaptchaを呼び出すべきではありませんか?どうやって?

「render」、「getResponse」、「execute」があります。どちらを使用すればよいですか?ドキュメントからは明らかではありません。

13
Kuqa

「目に見えない」recaptcha文書は十分に包括的なものではないことに同意します。これをどのように使用するかを理解する前に、コード例と「目に見える」レカプチャのドキュメントを掘り下げるのに時間がかかりました。

recaptcha APIについて最初に話しましょう:

grecaptcha.render(htmlEl, options, inherit)は、ページ上にキャプチャHTMLをレンダリングするJS APIメソッドです。デフォルトでは、recaptchaスクリプトは_class="g-recaptcha_を持つ要素を見つけてすぐにレンダリングしようとしますが、_?render=explicit_クエリパラメーターをrecaptchaスクリプトsrc urlに追加することでこの動作をオーバーライドできます。また、スクリプトがロードされたときよりも後の時点でrecaptcha _.g-recaptcha_要素がDOMにアタッチされたときに、このAPIを使用してオンデマンドでrecaptcha htmlをレンダリングすることもできます。このapiは、他のapiメソッドに渡すことができるID値を返しますが、渡されない場合、それらのapiのルックアップと参照は最初にページのrepcaptchaを参照します。

grecaptcha.getResponse(optional_id)はトークンを返します。トークンが空の文字列である場合、ユーザーがまだ検証されていない、つまりユーザーがキャプチャチャレンジを完了していないことを意味します。

grecaptcha.execute(optional_id) apiはrecaptchaチャレンジをプログラムでオンデマンドでトリガーします。このAPIは、「目に見えない」recaptchaにのみ適用できます。ユーザーがrecaptchaモジュールをクリックすると、表示されるrecaptchaチャレンジがトリガーされます。

grecaptcha.reset(optional_id)はチャレンジをリセットします。つまり、サーバーがrecaptcha apiサーバーでトークンの検証に失敗するたびに実行する必要があります(トークンは1回限りです)が、実装によっては、いつでもリセットすることができます。

今、データコールバックについて話しましょう:

_data-callback_は、グローバル名前空間関数の名前、つまりwindow ['nameOfFunction']としてアクセス可能な関数を渡すことができる属性です。このコールバックは、ユーザーが最終的にサーバーに渡すトークン値で正常に検証されるたびに呼び出されます。これはgrecaptcha.getResponse()によって返されるトークンと同じなので、技術的にはこの関数はまったく必要ありません。ただし、UIなどを更新する必要がある場合にユーザーが検証に合格したことを知らせるコールバックとして機能します。

何らかの理由でウィンドウネームスペースからこのコールバックにアクセスしたくない場合は、callbackキーを使用してoptionsオブジェクトのこのメソッドをgrecaptcha.render()に渡すことができます。注:_options.callback_は、HTMLで_data-callback_属性を渡すことと同等の文字列値を取ることができます。つまり、ウィンドウ名前空間の関数でなければなりません。ただし、_options.callback_も「関数」値を取ることができます。


次に、いくつかのサンプルコード:

[〜#〜] 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