5
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Java/SpringでreCAPTCHA v3を実装する

Last updated at Posted at 2020-01-03

はじめに

ググってもJava向けの記事がなかったのと、公式サイトは若干わかりづらかったのでまとめてみました。

公式リンク

参考リンク

登録方法

まずサービスを利用するために登録を行います。

お問い合わせフォームにreCAPTCHA v3を導入してみました!
⇒「reCAPTCHA v3の登録方法」を参照

実装方法

登録が済めば後は実装するだけです。

クライアント側

HTML

formタグ内に以下を追記。
JavaScriptによって取得したtokenをこのvalueに設定して、submitします。
Ajaxを使うなら、直接tokenをRequestパラメータに指定することによりこの記述は不要です。

hoge.html
<input type="hidden" name="recaptchaResponse" id="recaptchaResponse">

script読み込み部分に以下を追記。
自サイトでreCAPTCHAを使えるようにします。
(サイトキー)には登録時に取得したサイトキーを代入します。

hoge.html
<script src="'https://www.google.com/recaptcha/api.js?render=' + (サイトキー)"></script>

JavaScript

form submit時に実行される関数を以下のように実装。
actionに設定した値(以下では'contact_form')はreCAPTCHAからのResponseに格納されるので、サイト上のどこで実行されたかなどを設定しておくと分析とかに使えるかも。

hoge.js
$form = $(/* formを取得 */);
$button = $(/* form内のsubmitボタンを取得 */);

$button.click(function() {
		// reCAPTCHA v3用
		grecaptcha.ready(function () {
			grecaptcha.execute(サイトキー, {action: 'contact_form'}).then(function(token) {
				$('#recaptcha-response').val(token);

				// reCAPTCHA実装前に関数内に記述していた処理はここに記述				

				$form.submit();
			});
		});
});

バックエンド側

Controller

POST先のメソッドを以下のように実装。実際にはロジック部分はService層に切り出すこと。
BOT判定(if文の部分)については次のModelセクションで解説します。

HogeController.java
@RequestMapping(value = "/hoge", method = RequestMethod.POST)
public String hogePost(
		@Valid @ModelAttribute("hogeForm") HogeForm hogeForm,
		BindingResult bindingResult,
		HttpServletRequest request, SitePreference sitePreference, Model model) {

	String url = "https://www.google.com/recaptcha/api/siteverify?secret=" + シークレットキー + "&response=" + hogeForm.getRecaptchaResponse;
	RestTemplate restTemplate = new RestTemplate();
	RecaptchaResult result = restTemplate.getForObject(url, RecaptchaResult.class);

	log.info("reCAPTCHA result: " + result.toString());

	if (result.isSuccess()) {
		if ( 0.5 <= result.getScore()) {
			// BOTと判定されなかった場合の処理を記述
		} else {
			// BOTと判定された場合の処理を記述
		}
	} else {
		// reCAPTCHAに接続失敗した場合の処理を記述
	}
}

Model

reCAPTCHA APIのResponseを格納するModelを以下のように実装。
getterとsetterを自動生成するlombokを使用しています。
Responseの内容は公式を参照してください。

重要なこと

successプロパティはAPIの接続の成功・失敗を表すものであり、BOTかどうかの判定ではないことに注意する。
reCAPTCHAでは返却されたscoreプロパティ(0.0~1.0)を基にBOTかどうかを自プログラムで判断する。scoreが1に近いほどBOTの可能性が低く、0に近いほどBOTの可能性が高い。
Google公式 Interpreting the score曰く、最初の閾値は0.5でいいとのこと。

RecaptchaResult.java
package com.croooober.v1.cr_www.model.api;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class RecaptchaResult {
    private boolean success;
    private String challenge_ts;
    private String hostname;
    private float score;
    private String action;

    public RecaptchaResult() {
    }
}

また、Formオブジェクトにプロパティを追加。

HogeForm.java
private String recaptchaResponse;

うまく実装できていれば、以下のようにlog出力で結果を確認できると思います。

reCAPTCHA result: RecaptchaResult(success=true, challenge_ts=2020-01-08T04:19:27Z, hostname=hoge.com, score=0.9, action=contact_form)

感想

最初はAPIに投げればBOTかどうか判定してくれるものと思っていました。
実際にはscoreを基に自プログラムで判定する必要があって少しだけ混乱しました。

5
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?