Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

reCAPTCHA V3導入の問題点

More than 1 year has passed since last update.

結構ハマるなこれ。

ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪


------------------- ↓ 余談はここから ↓-------------------
スパム対策にGoogle謹製のreCAPTCHAを導入することは多いと思う。
I'm not a robot でパズルやらされる例のアレだが、
Version3.0ではあのパズルがなくなって、
AIで判別するようになるらしい。
実装はV2とほぼ一緒で簡単に終わったなと思った。

ところが、数日後、

投稿者数が減ったような気がする

という連絡が。

(゚-゚) こりゃあかんやつやも。

こちらとしてはGoogleの実装例そのまま載せたのだが、
エラーを解析した結果、
timeout-or-duplicate というエラーばかりだった。

マニュアルには

timeout-or-duplicate
The response is no longer valid: either is too old or has been used previously. 

https://developers.google.com/recaptcha/docs/verify
と記載されているが、
このtoo oldとは何時間のことなのか。
実際に測ってみたら。5分だった。

_人人人人人人人人_
> Too Old: 5分 <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^ ̄

有効期限を延ばす手段は管理画面とかにもない。
Googleさん、そりゃねーよ。
さて、困った。これで実装方法を大幅に変えなきゃならん。
方法は3つ。

  1. タイマーでtokenを再発行
  2. サブミットの直前で発行
  3. timeout-or-duplicateを許容する

(。_。) さて。。。


------------------- ↓ 本題はここから ↓-------------------

タイマーでtokenを再発行

コードはこんな感じになるだろうか

grecaptcha.ready(function() {
  grecaptcha.execute('reCAPTCHA_site_key', {action: 'user/register'});
  var ticker = setInterval(function(){
    try{
      grecaptcha.reset();
      clearInterval(ticker);
    } catch(e) {}
  },250);
}

一定時間が経過した時点でresetを実行する。
これでキーが再発行される(らしい)
setIntervalかsetTimeoutかはお好みで。

サブミットの直前で発行

コードはこんな感じになるだろうか
(Jquery記述で申し訳ない)

  grecaptcha.ready(function() {
    $('.recaptcha')
      .on('click', function () {
        grecaptcha
         .execute('reCAPTCHA_site_key', {action:'article/edit'})
         .then(function(token) {
           $('form:first').submit();
         });
      });
  });

サブミットボタン(type=button)を押したときに、
Googleからキーを発行して貰い、
それが完了したらsubmitを実行する流れ。

これであればタイムアウトが5分でも問題は起こらない。

timeout-or-duplicateを許容する

Googleサーバーにverify掛け、
bot判定(Success:false)されたときに結果JSONは以下のような感じになる。

{
  "success": false,
  "error-codes": [
    "timeout-or-duplicate"
  ]
}

このerror-codesを判別してtimeout-or-duplicateの時はそのまま受け付ける。


------------------- ↓ 後書はここから ↓-------------------

実際採用したのは3番目。
timeout-or-duplicateを許容するである。

タイマーはなるべく避けたかったし、
JSゴリゴリでテスト満載も避けたかったのがその理由。

参考記事:
https://stackoverflow.com/questions/48133487/getting-invisible-recaptcha-to-trigger-on-page-load

dozo
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away