WordPress

reCAPTCHAからCloudflare Turnstileに切り替えた話|自作フォームへの導入手順と気をつけること

このブログのお問い合わせフォームは、スパム対策を Google の reCAPTCHA から Cloudflare Turnstile に切り替えました。きっかけは、ブログを静的HTMLで公開する構成にしたときに、フォームの送信処理を自作したことです。

reCAPTCHA には何年もお世話になりましたが、使っていて気になる点がいくつかありました。この記事では、reCAPTCHA で困っていたこと、Turnstile を選んだ理由、自作フォームへの組み込み方と、使ってみて気をつける点をまとめます。

静的化の全体の話は「WordPressを静的HTML化して本番公開するまで」に書いています。

reCAPTCHAで困っていたこと

以前は Snow Monkey Forms に reCAPTCHA を設定していました(設定方法は「SnowMonkeyForms|フォームにreCAPTCHAを設置する方法」)。実際に困っていたのは次の3つです。

1. 右下のバッジと、表示速度への影響

reCAPTCHA v3 を入れると、画面の右下に reCAPTCHA のバッジが常に表示されます。スマホではページ上部へ戻るボタンなどと重なりやすく、デザインの邪魔になりがちでした。

バッジは、reCAPTCHA で保護していることをページ内に明記すれば CSS で非表示にできます(執筆時点の Google の FAQ による)。ただ、毎回その文言を入れる手間がかかります。

もう1つは表示速度です。reCAPTCHA v3 は、サイト内での動きを見てスコアを出す仕組みのため、フォームのないページにもスクリプトを読み込む設定にしているサイトがよくあります。そうすると、全ページで Google のスクリプトを読み込むことになり、PageSpeed Insights の点数にも影響します。

2. スパムが止まりきらない

reCAPTCHA v3 はチェックボックスや画像選択を出さない代わりに、0.0〜1.0 のスコアで「人間らしさ」を判定し、どこで弾くかはサイト側が決めます。しきい値を厳しくすると本物のお問い合わせまで弾く心配があり、ゆるくすると営業メールやスパムがそのまま届きます。結局、入れていても怪しいメールは届き続けていました。

3. Google Cloudへの移行と無料枠

いちばん大きかったのがこれです。reCAPTCHA は Google Cloud のサービスに統合され、従来のキー(Classic キー)は Google Cloud のプロジェクトに移行されることになりました。Google のドキュメントでは、2025年第4四半期から自動移行が始まり、2026年第1四半期に完了するとされています。

移行後も既存のキーはそのまま動きますが、キーの管理は Google Cloud コンソールで行うことになり、プロジェクトの所有権の招待を受け入れる必要があります。また、無料で使えるのは月10,000件の評価までで、それを超えて使うには課金の設定が必要です(執筆時点)。複数のクライアントサイトを1つのアカウントで管理していると、「どのプロジェクトに、どのサイトのキーが入っているか」を整理するだけでも一仕事です。

Turnstileを選んだ理由

Cloudflare Turnstile は、Cloudflare が提供する reCAPTCHA の代わりになる仕組みです。選んだ理由は次のとおりです。

このブログでも、Turnstile のスクリプトを読み込んでいるのはお問い合わせページだけです。ほかのページでは読み込んでいません。

自作フォームへの組み込み方

静的化したこのブログでは、PHP が動くのはフォームの送信処理の1ファイルだけです。Turnstile は「ブラウザでの表示」と「サーバーでの検証」の2か所に手を入れます。

フォーム側:ウィジェットを置く

Cloudflare のダッシュボードで Turnstile のウィジェットを作り、サイトキーとシークレットキーを発行します。フォームには、スクリプトとウィジェット用の要素を置くだけです。

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

<form action="/contact-send.php" method="post">
  <!-- 入力欄 -->
  <div class="cf-turnstile" data-sitekey="サイトキー" data-language="ja" data-theme="light"></div>
  <button type="submit">送信する</button>
</form>

ウィジェットの検証が終わると、フォームの中に cf-turnstile-response という名前でトークンが自動的に入り、ほかの入力内容と一緒に送信されます。

サーバー側:siteverifyで検証する

ここが一番大事なところです。ウィジェットを置いただけでは、スパム対策にはなりません。送られてきたトークンを、サーバーから Cloudflare の siteverify API に送って確認する必要があります。PHP で書くと、たとえば次のような処理です。

<?php
// シークレットキーは公開フォルダの外に置いた設定ファイルから読み込む
$config = require '/path/to/private/config.php';

$token = $_POST['cf-turnstile-response'] ?? '';

$ch = curl_init('https://challenges.cloudflare.com/turnstile/v0/siteverify');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => http_build_query([
        'secret'   => $config['turnstile_secret'],
        'response' => $token,
        'remoteip' => $_SERVER['REMOTE_ADDR'] ?? '',
    ]),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 10,
]);
$result = json_decode((string) curl_exec($ch), true);
curl_close($ch);

if (empty($result['success'])) {
    // 検証に失敗したら送信しない
    http_response_code(400);
    exit('送信を確認できませんでした。お手数ですが、もう一度お試しください。');
}

// ここからメール送信の処理

シークレットキーは、公開フォルダの外に置いた設定ファイルから読み込むようにしています。送信先のメールアドレスも同じ設定ファイルに入れて、公開されるファイルには書かないようにしました。

あわせて入れたハニーポット

Turnstile とは別に、人には見えない入力欄(ハニーポット)も入れています。画面には表示せず、「この欄は空のままにしてください」とラベルを付けておき、ここに何か入っていたら機械的な送信とみなして送信しない、という単純な仕組みです。手間がかからないわりに効果があるので、Turnstile と組み合わせておくと安心です。

ダッシュボードで実際の結果を見る

Cloudflare のダッシュボードでは、ウィジェットごとにチャレンジの結果をグラフで確認できます。下は、このブログのお問い合わせフォームの7日間の画面です。

Cloudflare Turnstileのダッシュボード(7日間)。チャレンジ49件のうち解決41件・未解決8件、Likely human 83.67%、Likely bot 16.33%、トークン検証41件
このブログのお問い合わせフォームの、7日間のダッシュボード

グラフを見ると、昼間にまとまって表示されたチャレンジはほとんどが解決(緑)で、人間によるアクセスと判定されています。一方、金曜と土曜の早朝に2件ずつある未解決(赤)は、どちらも100%「botらしい」と判定されていました。チャレンジを解けなければトークンは発行されないので、こうしたアクセスがトークンなしで送信してきても、サーバー側の siteverify で弾かれます。

もう1つ見ておきたいのが、右上の「Token validation」です。解決された41件と同じ数が表示されていて、サーバー側の siteverify がきちんと動いていることが確認できます。ここが0のままなら、ウィジェットは表示されていてもサーバーで検証していない、つまりスパム対策として機能していない状態です。

個人ブログなので件数は多くありませんが、reCAPTCHA v3 のようにスコアのしきい値で悩まなくても、「人間は通し、botらしいアクセスは通さない」結果がそのまま見えるのは安心できるところです。導入したら、自分でテスト送信して solved と Token validation に数字が入るかを確認しておくと、設定ミスにもすぐ気づけます。

使ってみて気をつけること

WordPressのフォームプラグインなら設定だけで使える

自作フォームでなくても、Turnstile は使えます。たとえば Contact Form 7 では、「お問い合わせ → インテグレーション」に Turnstile の項目があり、サイトキーとシークレットキーを入れるだけで、すべてのフォームにウィジェットが表示されます。表示位置を変えたいときは、フォームに [turnstile] タグを入れます。Contact Form 7 の公式サイトでも、特別な理由がなければ reCAPTCHA より Turnstile をすすめています。

ほかのフォームプラグインでも Turnstile に対応しているものが増えているので、reCAPTCHA の Google Cloud 移行をきっかけに見直してみるのもおすすめです。

まとめ

料金や無料枠、移行のスケジュールは今後も変わる可能性があります。導入するときは、Cloudflare と Google の公式ドキュメントで最新の情報を確認してください。

アバター
この記事を書いた人 トノムラマサシ

masashi Webサイト屋兼ブロガー|過去に企業常駐などを経て現在はフリーランスでディレクションとコーダーとして活動しております。JS大好きなのでJSの仕事依頼お待ちしております。京都在中で5人家族。