今更ではありますが、 reCAPTCHA v3 の設置を試したのでメモしておきます。
設定
reCAPTCHAのページにアクセスし、設定を進めていきます。
まずは「v3 Admin Console」をクリックしてログイン。
新規でプロパティを追加するので右上の「+」をクリック。
必要事項を記入、 reCAPTCHA v3 を選択し、設置するドメインを記述。
発行後、 reCAPTCHA のキー から「サイトキー」と「シークレットキー」を控えます。なお、シークレットキーは自分以外には見えないようにご注意を。
PHP プログラムにも記述しますが、それはフロントには見えないようにします。
これで準備は完了。
コード
次にコードを。
フォーム (HTML)
<form method="post" action="./procedure.php">
<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response"><!-- 追加 -->
<button type="submit" class="btn btn-primary">送信する</button>
</form>
まずは HTML 。必要なのは reCAPTCHA のトークンを value
に含むための hidden
な input
要素。
その他の部分は通常のフォームと同様に作っていきます。
<script src="https://www.google.com/recaptcha/api.js?render=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" defer></script><!-- 控えたサイトキーを render の後に記述 -->
<script src="./js/app.js" defer></script>
また、フォームの HTML で API と JavaScript の読み込みをします。
JavaScript (app.js)
window.addEventListener('load', () => {
const siteKey = `XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`; // 控えたサイトキーを記述
grecaptcha.ready(function() {
try {
// 全体を try catch で括ってエラーの場合にも備える
grecaptcha.execute(
siteKey,
{
action: 'homepage'
}
).then(function( token ) {
// API から返却されたトークンをセット
const recaptchaResponseDom = document.querySelector('#g-recaptcha-response');
recaptchaResponseDom.value = token;
});
} catch (e) {
console.error(e.message);
}
});
});
読み込む JavaScript は reCAPTCHa のスクリプトと API 読み込みを前提として専用のコードを記述していきます。
サンプルでは submit
ボタンクリック時にブラウザのデフォルトの submit の動作をキャンセル (e.preventDefault()
) して JS で submit するものが散見されたのですが、個人的にその挙動はさせたくなかったので API を叩いてトークンをセットする部分のみを記述しました。
PHP (procedure.php)
最後に submit 後の処理部分を。
<?php
$siteKeyID = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$secretKey = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY';
function err400() {
header('HTTP/1.1 400 Bad Request.');
include(__DIR__ . '/error.html');
exit;
}
function err500() {
header('HTTP/1.1 500 Internal Server Error.');
include(__DIR__ . '/error.html');
exit;
}
function success() {
header('HTTP/1.1 200 OK.');
include(__DIR__ . '/finish.html');
exit;
}
// filter_input で意図した値が拾えない場合は 400 を返却する
$captchaResponse = filter_input(INPUT_POST, 'g-recaptcha-response');
if(!isset($captchaResponse) || empty($captchaResponse) || !is_string($captchaResponse)) {
error_log('reCAPTCHA のレスポンスコードがセットされていません。');
err400();
}
// APIリクエスト
$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=' . $secretKey . '&response=' . $captchaResponse);
// APIレスポンス確認
$responseData = json_decode($verifyResponse);
// 認証に失敗した場合は 500 を返却する
// パターン1 デフォルト
if ($responseData->success) {
success();
} else {
error_log('error: reCAPTCHA の認証でエラーが発生しました。');
err500();
}
// パターン2 スコアも判定に使用し、あえて人間でも引っかかるように閾値を高くする。 0.9 前後が平均値の模様なので 0.95 を閾値にすると大体引っかかるようになる
if ($responseData->success && $responseData->score >= 0.95) {
error_log('info: reCAPTCHA の認証が成功しました。');
error_log('score:' . $responseData->score);
success();
} else {
error_log('error: reCAPTCHA の認証でエラーが発生しました。');
error_log('score:' . $responseData->score);
err500();
}
やっていることとしては以下。
g-recaptcha-response
(HTML 側で記述したname
属性) の POSTパラメータ を読み取り、それと冒頭で控えたシークレットキーで API へ突き合わせを実行- 結果は
file_get_contents()
等で取得、 JSON 形式なのでjson_decode()
でデコード - デコードしたオブジェクトの
success
,score
プロパティ を使用して判定の結果によりエラーか処理続行かを分岐
これで何度か手動で試験して、意図した挙動になったことを確認しました(パターン1はOK、パターン2はNG)。
参考
reCAPTCHA v3
- (新) Google reCAPTCHA V3 リキャプチャ設置、設定方法 – Blog | Samurai Web Works サムライウェブワークス -ロサンゼルスのウェブデザイン会社-
- reCAPTCHAv3を使ってみた – Qiita
- Google reCAPTCHA v3をコピペで簡単に導入
- TECHSCORE|reCAPTCHA v3 入れてみた | TECHSCORE BLOG
- サイトの入力フォームにreCAPTCHA v3 を導入する | Points & Lines
- Google reCAPTCHA の使い方(v2\/v3)