メール送信フォームのスパム対策で重宝されるGoogle reCAPTCHA。
そのV3では、閲覧者に画像確認ウイジェットが表示されず、バックグラウンドでスパムかどうかの判定をしてくれるスタイリッシュな仕様となっています。
そんな「reCAPTCHA V3」を設定したのでその内容などをメモメモ。
reCAPTCHA V3の手動実装の仕様
WordPressのプラグインを使っての実装ではなく、手動でWEB内の送信フォームなどにGoogle reCAPTCHA V3を組み込む使用です。
「reCAPTCHA V3」の実装の一番シンプルなのは、非同期ajaxとjQueryでごにょごにょしてformの送信ボタンの表示・非表示などで完結させる実装ができると思いますが、それは一般的ではないみたいになので、form側とサーバー側の連携でチェックする方式のをメモしておきます。
【基本的なreCAPTCHAのSPAM判定の理屈】
Google reCAPTCHA V3を実装する上で、その実装仕様・理屈を理解しておく必要があります。
1 まず入力フォーム画面でGoogle reCAPTCHAの判定用トークン(tokeb)を取得
2 送信ボタンが押されたら、トークンとシークレットキーを使ってAPIに判定結果を問い合わせる。
3 判定結果(response)を元にフォーム送信プログラム内で送信するかどうかを決める(条件分岐)
という流れですね。
なお、実装方法はプログラムをどう組むかの問題なので、パターンはいくらでもあると思います。
Formを表示するhtml側(phpでも可)での設定
1 reCAPTCHAのAPIを読み込み
<script src=”https://www.google.com/recaptcha/api.js?
render=サイトキー”></script>
2 もともとある入力FORM内のsubmitボタン(input type=”submit”)を非表示か消す ※3のボタンで送信を制御するため
2 送信ボタンが押されたらトークンを取得してPOSTで送るスクリプトを組む。
実装上大きな中点として、トークンの有効期限の問題があります。発行されるトークンの有効期限は2分です。送信ボタンが押されてから2分ではなく、取得されてから2分です。
フォームの入力に2分以上かかることも往々にしてありますので、トークンの取得を送信ボタンが押された時に設定する必要があります。
※つまり、Google公式に載っているスクリプトはそのままでは使えない。
一つの方法として、jQueryのeventDefault()を使用し、送信を停めてトークンを取得してから送信するという方法があります。
jQuery(function($){
$(‘フォ―ム名指定’).submit(function(event) {
event.preventDefault();
grecaptcha.ready(function() {
grecaptcha.execute(~~~~
}}
これでトークンの期限問題を回避できます。
なお、このスクリプト内に、トークンをPOST送信に加えるスクリプも入れておきます。
メールを送信するスクリプト側での設定
Googleでの説明では、サーバー側での設定という説明になっていますが、要はメールを送信するphpプログラム内でreCaptchaの判定を元に送信するかしないかを制御するスクリプトを追加します。
phpのメール送信プログラムがあることを前提に話しますが、判定→送信の流れはこんな感じになります。
(1) postでreCAPTHCAのトークンを受け取る
(2) そのトークンとシークレットキーを使い、reCAPTCHAのAPIに問い合わせて結果をもらう
phpなら、file_get_contents()やcURLを使用してAPIから取得するのが一般的です。
(3) 結果からメールを送信させるかどうかの条件判定を行う
例)if ($score >= 0.5) {~~~}
(4) 条件がOKなら送信プログラムを実行する
自分が利用してる送信プログラムを見て、どこにどうプログラムを入れるかは考えなければなりません。セッションの管理と条件判定の位置などを考えて完璧に組み込もうとするとプログラムの初歩から少し毛が生えた程度の知識が必要かもしれません。
サンプルとして、POSTで取得したトークンをAPIに送り、結果のJSONを取得して判定する流れを上げてみます。
if ( isset( $_POST[ ‘g-recaptcha-response’ ] ) )
{
$url = ‘https://www.google.com/recaptcha/api/siteverify’;
$data = array(
‘secret’ => シークレットキー, ‘response’ => $_POST[ ‘g-recaptcha-response’ ]
);
$context = array(
‘http’ => array(
‘method’ => ‘POST’,
‘header’ => implode(“\r\n”, array(‘Content-Type: application/x-www-form-urlencoded’,)),
‘content’ => http_build_query($data)
)
);
$api_response = file_get_contents($url, false, stream_context_create($context));
$result = json_decode( $api_response );
if ( $result->success )
{
$score =$result->score;
//スコアによる送信判定処理
if ($score >= 0.5) // 0.5以上なら合格
{
// reCAPTCHAで合格した場合の処理、フラグ立てや送信への流れ
print (“送信前認証に成功しました(スコア$score )”); // デバッグ用
}
else
{
// reCAPTCHAで不合格判定の場合の処理 エラーフラグ立て等。
print (“スパムと判定されました。”);
}
}
else
{
// 結果の取得ができなかった場合の処理・エラーフラグなど
$error_flag = 1;
}
}
Google reCAPTCHA V3では、スパム判定のスコア(0.0~1.0)を取得できますので、そのスコアで送信するかどうかを決めればいいと思います。
《参考》APIから戻って来るresponse(Site Verify Response)
{
“success”: true|false, // whether this request was a valid reCAPTCHA token for your site
“score”: number // the score for this request (0.0 – 1.0)
“action”: string // the action name for this request (important to verify)
“challenge_ts”: timestamp, // timestamp of the challenge load (ISO format yyyy-MM-dd’T’HH:mm:ssZZ)
“hostname”: string, // the hostname of the site where the reCAPTCHA was solved
“error-codes”: […] // optional
}
なお、余談ではありますが、responseで取得するキーの”success”の値なんですが、デバッグ的に$json -> successを表示させると”1″になりますね。てっきり”true”なのかと思いきや”1”です。バグってるのかと無駄な時間を使いましたが、PHPでは、true=1であってるそうです・・・。ちなみにfalseは””みたいな。
《補足》
actionは、web-formなど、「-」ハイフンを入れるとエラーになります。
コメント