← 戻る

reCAPTCHA → Cloudflare Turnstile への移行


背景

  • Google reCAPTCHA は Google infrastructure 依存
  • Cloudflare Pages への移行に伴い、Cloudflare 内部で完結する Turnstile に変更

差異比較

項目Google reCAPTCHACloudflare Turnstile
チャレンジロボット判定ロボット判定
パフォーマンス速いより高速(CF エッジで実行)
プライバシーGoogle に送信CF 内部で完結
料金無料無料(CF Pages Free含む)
デプロイGoogle Consolewrangler.toml + env var
キャプチャUIGoogle ブランドCF ブランド(かつシンプル)

実装

1. Cloudflare 側

# wrangler.toml
[[env.production.r2_buckets]]
name = "TURNSTILE_SECRET_KEY"
binding = "TURNSTILE_SECRET_KEY"

[env.production.vars]
TURNSTILE_SITE_KEY = "1x..."

2. フロント(Astro コンポーネント)

---
import { TURNSTILE_SITE_KEY } from 'astro:env/client';
---
<form id="contact-form">
  <input type="email" name="email" required />
  <textarea name="message" required></textarea>

  <!-- Turnstile ウィジェット -->
  <div class="cf-turnstile" data-sitekey={TURNSTILE_SITE_KEY}></div>

  <button type="submit">送信</button>
</form>

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

<script>
  document.getElementById('contact-form')?.addEventListener('submit', async (e) => {
    e.preventDefault();

    const token = window.turnstile.getResponse();
    if (!token) {
      alert('Please complete the verification');
      return;
    }

    const formData = new FormData(e.target);
    formData.append('cf-turnstile-response', token);

    await fetch('/api/contact', {
      method: 'POST',
      body: new URLSearchParams(formData)
    });
  });
</script>

3. バック(Pages Functions)

// functions/contact.ts
export const onRequest: PagesFunction = async (context) => {
  const formData = await context.request.formData();
  const token = formData.get('cf-turnstile-response');

  // Turnstile トークン検証
  const verifyUrl = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
  const verifyResponse = await fetch(verifyUrl, {
    method: 'POST',
    body: JSON.stringify({
      secret: context.env.TURNSTILE_SECRET_KEY,
      response: token
    })
  });

  const data = await verifyResponse.json();

  if (!data.success) {
    return new Response('Verification failed', { status: 400 });
  }

  // フォーム処理続行...
};

メリット

  • プライバシー: Google と通信なし
  • 速度: Cloudflare エッジで即座に検証
  • 一体性: Pages + Turnstile で CF 内完結
  • UI/UX: Turnstile のキャプチャがシンプル

移行時の注意

  • Turnstile は reCAPTCHA v3(スコアベース)ではなく v2 相当(チャレンジベース)
  • 既存のスコアロジックがあれば別途実装が必要