ホームページ制作 オフィスオバタ

Google reCAPTCHA V3をフォームに埋め込んでみた

お問い合わせフォーム等のツールは、お客様とお店をつなぐ重要な役割を担っています。
しかしその反面、スパムなど悪用されることもあります。

これを何とかするのがrecaptchaと呼ばれる機能です。

時たま、数字を入力したり、写真を選んだりするフォームがありますが、そのことです。

今回は google のreCAPTCHAを導入する機会があったので、忘備録として記録いたします。

とはいえ、どうやって導入するの?

reCAPTCHAを導入すればセキュリティが向上することはわかります。
でもどうやればいいの?

そもそもどうやればいいのかがさっぱりです。
なのでググって調べたところ、以下の手順を踏めば導入できることがわかりました。

  1. google reCAPTCHA管理画面にドメインを登録する
  2. お問い合わせフォームにトークン処理を埋め込む
  3. プログラム側にトークン判定処理をも盛り込む

作業としたらこの3つですがなぜかしっくりきません。
それは、理屈がよくわからないからです。

でも理屈が理解できると、作業の意味が分かるようになりました。
reCAPTCHAの理屈について、以下に記載します。

reCAPTCHAが不正投稿を判定する仕組み

これらを踏まえて作ってみたものがこちらです。

一見難しそうに感じますが、要は「判定をgoogleに丸投げするために必要な情報をgoogleに送る」ということをやってやればよいのです。

(1)google reCAPTCHA管理画面にドメインを登録する

まずはgoogleにドメインを登録します。
ドメインを登録することで、該当サイトでの不正投稿チェックができるようになります。

google recAPTCHA管理画面

新規登録を行う

管理画面を開いたら、新規登録を意味する「+」ボタンをクリックします。

ドメイン等必要事項を入力します

①ラベル

管理画面上の識別目的のための名称。
自分がわかりやすい名称を付けます。

②reCAPTCHAタイプ

V3方式か、V2方式を選択します。
V2方式は入力者が数字や写真選択を行うのに対し、V3方式は入力者が何も選択する必要はなく全自動でgoogleが不正判断します。

個人的にはV3のほうがセキュリティ性が高くオススメです。

③ドメイン

reCAPTCHAを埋め込むドメインを指定します。

④利用条件に同意

同意にチェックを入れます。
チェックを入れないとreCAPTCHAは使用できません。

⑤送信ボタンをクリック

送信ボタンを押し、登録を実行します。

サイトキー/シークレットキーを書き留めておく

登録後サイトキーとシークレットキーが表示されますので、書き留めておきます。
※後から管理画面で確認することも可能です。

サイトキーはHTMLに埋め込みします。
シークレットキーはプログラム側でgoogleから不正判断を確認するために使用します。

以上でreCAPTCHA管理画面への登録作業は完了です。

(2)HTMLへreCAPTCHAを埋め込む

管理画面にドメインを登録したら、今度はフォームのHTMLにreCAPTCHAを動作させるためのスクリプトを埋め込みます。
原則コピペだけで済みますが、フォームのIDなどは書き換えをする必要があります。

埋め込むものは以下の2つです。

■JSファイル

reCAPTCHAを動作させるためのJSファイルを読み込みます。
パラメータとして「サイトキー」を記述します。

<script src="https://www.google.com/recaptcha/api.js?render=[サイトキー]"></script>

■トークン格納ブロック

照合のためのトークンを埋め込むINPUTを記述します。
hidden(非表示)INPUTです。



<input type="hidden" name="recaptchaToken" id="recaptchaToken">

■スクリプト

送信ボタンが押されたときの動作を埋め込みます。
ちなみに、送信ボタンが押されたら上記項目にトークンを埋め込み、送信処理を実行しています。

<script>
document.getElementById("[メールフォームID]").addEventListener('submit', onSubmit);
 
function onSubmit(e) 
{
	e.preventDefault();
	grecaptcha.ready(function() 
	{
		grecaptcha.execute('[サイトキー]', {action: 'submit'}).then(function(token)
		{
			// Add your logic to submit to your backend server here.
			var recaptchaToken = document.getElementById('recaptchaToken');
			recaptchaToken.value = token;
			document.getElementById("mail_form").submit();
		});
	});
}
</script>

これだけだとわかりにくいので、冒頭サンプルのHTMLソースを記載します。

<!doctype html>
<html>
<head>
<meta charset="shift_jis">
<title>reCAPTCHAテスト</title>
<script src="https://www.google.com/recaptcha/api.js?render=[サイトキー]"></script>
<style type="text/css">
form 
{
	width: 400px;
	margin-right: auto;
	margin-left: auto;
	text-align: center;
}
input[type=submit]
{
	height: 40px;
	width: 100px;
}
.OK
{
	color: #3C0;
	padding: 10px;
	border: 10px solid #3C0;
}
.NG
{
	color: #F00;
	padding: 10px;
	border: 10px solid #F00;
}

</style>
</head>
<body>

<form action="" method="post" enctype="multipart/form-data" id="mail_form">
<input type="hidden" name="recaptchaToken" id="recaptchaToken">
<p>
送信ボタンを押してください。<br>
送信完了後F5ボタンを押し、<br>二重送信するとエラーになります。
</p>
<input name="" type="submit" value="送信">
<p><a href="/">リセット</a></p>
</form>
<script>
document.getElementById("mail_form").addEventListener('submit', onSubmit);
 
function onSubmit(e) 
{
	e.preventDefault();
	grecaptcha.ready(function() 
	{
		grecaptcha.execute('[サイトキー]', {action: 'submit'}).then(function(token)
		{
			// Add your logic to submit to your backend server here.
			var recaptchaToken = document.getElementById('recaptchaToken');
			recaptchaToken.value = token;
			document.getElementById("mail_form").submit();
		});
	});
}
</script>

</body>
</html>

HTML部分はスクリプトを埋め込めばOKです。
ここまで埋め込み出来れば、右下にreCAPTCHAバナーが表示されるようになります。
(サーバーにUPしないとバナーは表示されません。)

(3)プログラム照合チェック処理を埋め込む

最後はプログラム側に照合チェック処理を埋め込みます。
要は不正投稿かどうかをgoogleツールを利用して判断します。

googleツールができるのはOKかNGかの結果だけで、NGであった場合の処理は自分で何とかします。
このあたりがちょっとわかりにくいかもしれません。

具体的なチェック方法

プログラム側での具体的なチェック方法は、以下のように記述します。

$result = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=[シークレットキー]&response=[トークンコード]");
$chk = json_decode($result);

if ($chk->success == true)
{

    // チェックOKの処理
}

else
{
    // チェックNGの処理
}

シークレットキーは、google管理画面に登録したときに表示されたキーをセットします。
トークンコードは、HTML側から送信されたトークンコードをセットします。

googleからの診断結果を見て処理を判断するため、ロジックを修正する必要は出ますがさほどではありません。

HTMLを含めたソースはこちら

<?php
$RECAPTUER = "[シークレットキー]";

$message = null;

if (isset($_REQUEST["recaptchaToken"]) == true)	/* 送信ボタンが押された ? */
{
	/** トークンチェック */
	$token = $_REQUEST["recaptchaToken"];

	if (token_chk($token) == true)	/* トークンチェックOK */
	{
		$message = "<p class=\"OK\">reCAPTCHAチェックOKです。</p>";
	}
	else
	{
		$message = "<p class=\"NG\">reCAPTCHAチェックNGです。</p>";
	}
}

function token_chk($token)
{
	global $RECAPTUER;

	/** ステータス初期化 */
	$sts = false;

	$result = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=${RECAPTUER}&response=${token}");
	$chk = json_decode($result);

	if ($chk->success == true)	/* トークンエラー */
	{
		$sts = true;
	}

	/** 処理終了 */
	return $sts;
}

?>
<!doctype html>
<html>
<head>
<meta charset="shift_jis">
<title>reCAPTCHAテスト</title>
<script src="https://www.google.com/recaptcha/api.js?render=[サイトキー]"></script>
<style type="text/css">
form 
{
	width: 400px;
	margin-right: auto;
	margin-left: auto;
	text-align: center;
}
input[type=submit]
{
	height: 40px;
	width: 100px;
}
.OK
{
	color: #3C0;
	padding: 10px;
	border: 10px solid #3C0;
}
.NG
{
	color: #F00;
	padding: 10px;
	border: 10px solid #F00;
}

</style>
</head>
<body>

<form action="" method="post" enctype="multipart/form-data" id="mail_form">
<?php echo $message; ?>
<input type="hidden" name="recaptchaToken" id="recaptchaToken">
<p>
送信ボタンを押してください。<br>
送信完了後F5ボタンを押し、<br>二重送信するとエラーになります。
</p>
<input name="" type="submit" value="送信">
<p><a href="/">リセット</a></p>
</form>
<script>
document.getElementById("mail_form").addEventListener('submit', onSubmit);
 
function onSubmit(e) 
{
	e.preventDefault();
	grecaptcha.ready(function() 
	{
		grecaptcha.execute('[サイトキー]', {action: 'submit'}).then(function(token)
		{
			// Add your logic to submit to your backend server here.
			var recaptchaToken = document.getElementById('recaptchaToken');
			recaptchaToken.value = token;
			document.getElementById("mail_form").submit();
		});
	});
}
</script>

</body>
</html>

HTML部分でreCAPTCHAのトークンコードを生成し、プログラム側でシークレットキーとトークンコードをパラメータとして渡して、不正かどうかのチェック結果を受け取っています。

reCAPTCHAが分かりにくいのは「埋め込み部分」

reCAPTCHAは導入すれば強力なセキュリティツールとなります。
しかし今回やってみて思ったことは、「埋め込み部分がわかりにくい」という点です。

サイトキーなど、登録者事にことなるキーなど単純にコピーペーストしただけでは動作しません。
また送信ボタンにJqueryを使用していた場合、記述方法を変更する必要も出てきます。

HTML部分を完成させても、プログラム側でチェック処理を埋め込みしなければ最終的なチェックはできません。

ツールとして確立はしていますが、設置にはそれなりの技術レベルが求められると感じました。

それでも、今後必要になってくるツールではあります。
難易度が高くても1度埋め込みした経験があれば、2回目以降は簡単にできます。

また本記事がお役に立てば幸いです。

モバイルバージョンを終了