仮会員登録多すぎ問題
仮会員登録多すぎる。
仮会員登録から飛んでくるメールが多い。
そのくせ、本会員登録は一切ない。
恐らくはBotが何のためか分からないが、仮会員登録しているみたい。
ということで、Google様のreCAPTCHAを入れてみる。
reCAPTCHAとは
reCAPTCHAとはGoogle様のサービスで、サイト内の動きからそれがBotかどうかを判断してくれるサービスである。
現在は以下の3タイプがある。
v1 : 画像に書かれている難読文字を判断させる。
v2 : 「私はロボットではりません」にチェックを入れる、怪しければ信号機等の映った画像を選ばせる。
v3 : ボタンを押したらそれまでの動きからスコアを出して、スコアを元にどうするかは開発者任せ
v1は画像解析ツールとのいたちごっこの末、人間さえも判断しづらくなったので、現在は、v2とv3を状況と好みに応じて使っているらしい。
今回はv3を入れてみる。
v3はスコアから、どういうふるまいを行うかを開発者側で実装する必要があるみたいだが、まぁ、ある程度のスコアを下回ったら有無も言わさず404にでも飛ばせばいいや。
reCAPTHCA v3 の概要図
以下が流れ図、submitの代わりにbuttonを用意して、buttonが押されたら、reCAPTHCAへサイトキーを送り、トークンを貰ってコールバックしてくるので、貰ったトークンを含めてsubmitしてあげる。
サーバイサイドでアクセストークンとシークレットキーのセットで検証結果を取得する。
reCAPTCHA 前準備
まずは、reCAPTCHAの管理画面でサイトを登録
https://www.google.com/recaptcha/admin
※ドメインの所にローカル環境も入れておかないと、開発中に確認できない。
作成すると、サイトキーとシークレットキーというのが発行される。
クライアントサイド実装
クライアントサイドサイドを実装する。
自動で取得したトークン貼り付けてくれる方法と、ちゃんと自分でPOSTしたい方法の2種類あるみたいだけど、動きゃいいのでお手軽な前者で。
まずは、以下をどっかに貼り付ける
<script src="https://www.google.com/recaptcha/api.js"></script>
んで、ボタンを配置
<button class="g-recaptcha"
data-sitekey="取得したサイトキー"
data-callback='reCaptchaCallbackSubmit'
data-action='submit'>規約に同意してメールを送信</button>
このボタンを押したら、googleにこのボタン押したのがBotかどうか判断してもらうために、情報を送る模様。
その後、tokenを貰って戻ってきて指定された関数を実行する。
上記では戻ってきた後、reCaptchaCallbackSubmitが実行される。
んで、コールバックされた関数で、submitしてあげる。
tokenは自動でsubmitの際にpostされているみたい。
これがいわゆるお手軽版なる理由のようである。
お手軽版じゃないほうは、自分でinputのhiddenタグにtokenをセットする必要がある模様。
function reCaptchaCallbackSubmit(token) {
$('#Signup form').submit();
}
サーバーサイド実装
サーバーサイドを実装する。ここではPHP で書いていくが、多分やることはどの言語でも変わらなさそう。
とりあえず以下のように実装した。
//Bot確認。とりあえず0.5以下はBotと判断
$recapResult = $this->getResltReCaptcha();
if($recapResult->score < 0.5){
throw new NotFoundException();
}
private function getResltReCaptcha(){
$secretKey = 'シークレットキー';
$captchaResponse = $_POST['g-recaptcha-response'];
// APIリクエスト
$verifyResponse = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secretKey}&response={$captchaResponse}");
// APIレスポンス確認
$responseData = json_decode($verifyResponse);
//チェックが成功したか判断
if(!$responseData->success){
$this->log('recaptcha error:'.print_r($responseData, true));
throw new Exception('reCaptchaのチェックに失敗');
}
return $responseData;
}
要するにクライアントサイドから自動でPOSTされたトークン ‘g-recaptcha-response’ と、最初の設定時に貰ったシークレットキーの二つを使って、google様に先ほどのアクセスはいかがでしたでしょうかとお伺いを立てる。
成功すると、scoreを持ったJSONがもらえるので、あとはscoreの値で動作を判断する。
scoreは0.0~1.0の幅らしいので、とりあえず0.5以下は今回はBotと判断して404を返却しておく。
(CakePHP4で書いてるので生PHPと謎メソッドでてきたりするけど気にしないで)
結果
うまく動作して、右下にアイコンがでるようになった。
動作は特に何も変わらないが、結果として毎日何通も届いていた仮会員登録メールが一通も届かなくなった。
ただ、reCAPTCHAが0.5以下を検知したのかと思いきや、不審なリクエストは0%のまま。
検知してはじくようになったというより、一切アクセスされなくなった。
これはreCAPTCHAの効果というより、submitボタンの代わりにbutonを置いて、callbackでsubmitメソッドをたたくようにしたことが理由なのかもしれない。
botはemailとsubmitがあったら何かをしようとしている?
まぁ、何にせよ静かになった。