結構ハマるなこれ。
ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪
------------------- ↓ 余談はここから ↓-------------------
スパム対策に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つ。
- タイマーでtokenを再発行
- サブミットの直前で発行
- 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