背景
- Google reCAPTCHA は Google infrastructure 依存
- Cloudflare Pages への移行に伴い、Cloudflare 内部で完結する Turnstile に変更
差異比較
| 項目 | Google reCAPTCHA | Cloudflare Turnstile |
|---|
| チャレンジ | ロボット判定 | ロボット判定 |
| パフォーマンス | 速い | より高速(CF エッジで実行) |
| プライバシー | Google に送信 | CF 内部で完結 |
| 料金 | 無料 | 無料(CF Pages Free含む) |
| デプロイ | Google Console | wrangler.toml + env var |
| キャプチャUI | Google ブランド | 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 相当(チャレンジベース)
- 既存のスコアロジックがあれば別途実装が必要