Cloudflare TurnstileとSupabase Edge Functionsでフォームを最強に守る方法

Cloudflare TurnstileとSupabase Edge Functionsでフォームを最強に守る方法

Cloudflare TurnstileとSupabase Edge Functionsでフォームを最強に守る方法

はじめに:スパムからフォームを守る最強の盾

ウェブサイトのフォームは、ユーザーとの貴重な接点です。しかし、同時にスパム攻撃の標的にもなりがちです。大量のスパムメールや不正なデータ送信は、ウェブサイトのパフォーマンスを低下させ、サーバーリソースを浪費します。従来のCAPTCHAはユーザーエクスペリエンスを阻害する可能性がありますが、Cloudflareの新しいサービスであるTurnstileを使えば、その心配も解消できます。本記事では、Cloudflare TurnstileとSupabase Edge Functionsを組み合わせることで、フォームを安全に保護し、同時に優れたユーザーエクスペリエンスを実現する方法を詳しく解説します。

Cloudflare Turnstileとは?無料のCAPTCHA代替サービス

Cloudflare Turnstileは、従来のCAPTCHAに代わる、無料のボット対策サービスです。Turnstileは、高度な機械学習アルゴリズムを用いて、人間とボットを区別します。従来のCAPTCHAのようにユーザーに複雑なパズルを解かせる必要がないため、ユーザーエクスペリエンスを大幅に向上させることができます。

Turnstileは、以下の3つのモードを提供しています。

  • Managed: Cloudflareが、ユーザーごとに最適なチャレンジ(表示される認証方法)を自動的に決定します。ユーザーは、画像やテキストを解読する必要はありません。
  • Invisible: ユーザーに一切のチャレンジが表示されません。バックグラウンドで検証が行われるため、ユーザーはスムーズにフォームを送信できます。これは、ユーザーエクスペリエンスを最大限に重視する場合に最適な選択肢です。
  • Custom: 独自のカスタムチャレンジを設計・実装できます。高度なカスタマイズが必要な場合に利用可能です。

本記事では、主にManagedモードとInvisibleモードの使い方を解説します。

攻撃の事例:なぜフォームの保護が重要なのか?

筆者のウェブサイトでは、Launch Weekのチケット販売に仮想チケットシステムを利用していました。その際、悪意のあるユーザーが、短時間に数千枚のチケットを不正に作成しようとした事例が発生しました。この事例は、フォームの適切な保護がいかに重要であるかを明確に示しています。

この攻撃を防ぐために、Cloudflare Turnstileを導入し、フォームへのアクセスを安全に制御することにしました。

Cloudflare Turnstileの設定:ステップバイステップガイド

Cloudflare Turnstileの設定は簡単です。以下の手順に従ってください。

  1. Cloudflareダッシュボードへのログイン: まず、Cloudflareのダッシュボードにログインします。

  2. Turnstileへのアクセス: ダッシュボードからTurnstileサービスにアクセスします。

  3. 新しいサイトの追加: 「新しいサイトを追加」ボタンをクリックして、保護したいウェブサイトを追加します。ここでは例として edge-functions をサイト名として使用します。ドメイン名は、テスト段階では localhost で問題ありません。

  4. ウィジェットタイプの選択: ManagedモードまたはInvisibleモードを選択します。ManagedモードはCloudflareが最適なチャレンジを選択し、Invisibleモードはユーザーに何も表示せずに検証を行う、という違いがあります。ユーザーエクスペリエンスを優先するならInvisibleモードがおすすめです。本記事では、Managedモードで開始し、必要に応じてInvisibleモードへの切り替え方法についても説明します。

  5. Site KeyとSecret Keyの取得: 設定完了後、Site KeyとSecret Keyが発行されます。これらのキーは、クライアントサイドとサーバーサイドの統合に必要となる重要な情報です。Secret Keyは絶対に公開しないでください。

クライアントサイドの統合:Reactアプリケーションへの実装

このセクションでは、ReactアプリケーションにCloudflare Turnstileを統合する方法を説明します。

  1. div要素の追加: フォームに、Cloudflare Turnstile専用のdiv要素を追加します。このdiv要素には、data-sitekey属性でSite Keyを設定します。

    <div className="cloudflare-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
    

    YOUR_SITE_KEYの部分には、Cloudflareダッシュボードで取得したSite Keyを貼り付けます。

  2. Cloudflare Turnstile JavaScriptスクリプトのインポート: Next.jsアプリケーションでは、next/scriptコンポーネントを使用して、Cloudflare TurnstileのJavaScriptスクリプトをインポートします。strategy="afterInteractive" を設定することで、ページの読み込みを妨げずにスクリプトをロードできます。

    import Script from 'next/script';
    
    <Script
        src="https://challenges.cloudflare.com/cdn-cgi/challenge-platform/hcaptcha/turnstile/v1/api.js"
        strategy="afterInteractive"
    />
    
  3. フォーム送信ハンドラの変更: フォーム送信ハンドラを修正し、Cloudflare Turnstileのレスポンスを取得するようにします。Turnstileは、フォームにcf-turnstile-responseという名前の非表示の入力フィールドを追加します。このフィールドからレスポンストークンを取得します。

    const handleSubmit = async (e) => {
        e.preventDefault();
        const formData = new FormData(e.target);
        const turnstileResponse = formData.get('cf-turnstile-response');
    
        // turnstileResponse をSupabase Edge Functionに送信
        // ...
    };
    

サーバーサイドの検証:Supabase Edge Functionsでの実装

クライアントサイドから取得したトークンを、Supabase Edge Functionsを用いてCloudflare APIで検証します。

  1. Supabase Edge Functionsの新しい関数の作成: Supabaseダッシュボードで新しいEdge Functionを作成します。ここでは、cloudflare-turnstileという名前の関数を作成します。

  2. CORS設定: クライアントサイドから関数にアクセスできるように、CORS設定を行います。access-control-allow-originヘッダーを適切に設定します。これを共有フォルダに保存することで、コードの再利用性を高めます。

    // shared/corsHeaders.js
    export const corsHeaders = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    };
    
  3. オプションリクエストの処理: ブラウザからのプレフライトリクエスト(OPTIONSリクエスト)を処理します。プレフライトリクエストには、CORSヘッダーを返すだけで十分です。

    // cloudflare-turnstile.js
    export async function POST(req) {
        if (req.method === 'OPTIONS') {
            return new Response(null, { headers: corsHeaders });
        }
    
        // ...
    }
    
  4. トークン検証: POSTリクエストを受け取り、クライアントサイドから送信されたトークンをCloudflare APIで検証します。この検証には、Secret Keyが必要です。Secret KeyはSupabase Secretsに安全に保存し、Deno.env.getを使って取得します。

    import {corsHeaders} from './shared/corsHeaders.js';
    const secretKey = Deno.env.get('CLOUDFLARE_TURNSTILE_SECRET_KEY') || ''; // Secret Keyを取得
    const token = (await req.json()).token; // クライアントサイドから送信されたトークンを取得
    const ipAddress = req.headers.get('cf-connecting-ip') || ''; // IPアドレスを取得
    
    const response = await fetch(`https://challenges.cloudflare.com/cdn-cgi/challenge-platform/hcaptcha/turnstile/v1/verify?secret=${secretKey}&response=${token}&remoteip=${ipAddress}`, {
        method: 'POST',
    });
    
    const result = await response.json();
    
    if (result.success) {
        return new Response(JSON.stringify({ success: true }), { headers: corsHeaders });
    } else {
        return new Response(JSON.stringify({ success: false, error: result.error_codes }), { headers: corsHeaders });
    }
    
  5. .envファイルの設定: Secret Keyを .env ファイルに格納します。

    CLOUDFLARE_TURNSTILE_SECRET_KEY=YOUR_SECRET_KEY
    
  6. 関数のデプロイとローカル実行: 作成したEdge FunctionをSupabaseにデプロイし、ローカルでテストします。supabase functions serve コマンドを実行して、ローカルサーバーを起動します。

クライアントサイドとサーバーサイドの連携:最終的な実装

クライアントサイドでは、フォーム送信時にcf-turnstile-responseから取得したトークンを、Supabase Edge Functionに送信します。サーバーサイドでは、そのトークンを検証し、検証が成功した場合のみ、データベースへのデータ書き込みなどの処理を実行します。

まとめ:安全で快適なフォーム体験の実現

Cloudflare TurnstileとSupabase Edge Functionsを組み合わせることで、ウェブサイトのフォームを安全に保護し、同時にユーザーエクスペリエンスを向上させることができます。本記事で紹介した手順に従うことで、スパム攻撃からフォームを守り、安全で快適なウェブサイトを提供できます。

よくある質問(FAQ)

Q1: Secret Keyを安全に管理するにはどうすれば良いですか?

A1: Secret Keyは、決して公開しないでください。Supabase Secretsなどの安全な秘密管理サービスを利用することを強く推奨します。本記事ではSupabase Secretsを使用しています。

Q2: Invisibleモードを使用するメリットは何ですか?

A2: Invisibleモードでは、ユーザーにCAPTCHAが表示されません。そのため、ユーザーエクスペリエンスを最大限に高め、スムーズなフォーム送信を実現できます。

Q3: 他のフレームワークでもCloudflare Turnstileは使用できますか?

A3: はい。Cloudflare Turnstileは、Reactだけでなく、さまざまなフロントエンドフレームワークやバックエンド環境で使用できます。クライアントサイドとサーバーサイドの統合方法がフレームワークによって異なる点に注意してください。

Q4: Turnstileの検証に失敗した場合、どうすれば良いですか?

A4: 検証に失敗した場合は、ユーザーにエラーメッセージを表示するか、フォームの再送信を促すなど、適切なエラー処理を実装してください。本記事では、エラーコードを含むエラーメッセージを返しています。

Q5: Cloudflare Turnstileは完全にスパムを防止できますか?

A5: Cloudflare Turnstileは、高度なボット対策を提供しますが、100%のスパム防止を保証するものではありません。高度なボットは、Turnstileを回避する可能性があります。複数のセキュリティ対策を組み合わせることで、より堅牢なシステムを構築できます。

今後の展望:より高度なボット対策

本記事では、Cloudflare TurnstileとSupabase Edge Functionsを用いた基本的なフォーム保護の方法を解説しました。今後は、より高度なボット対策として、以下のような対策を検討する事が考えられます。

  • IPアドレス制限: 特定のIPアドレスからのアクセスを制限する。
  • レート制限: 短時間内のアクセス数を制限する。
  • honeypot: スパムボットを検知するためのトラップを設置する。
  • reCAPTCHA Enterprise: より高度なボット検知機能を持つreCAPTCHA Enterpriseの利用。

これらの対策を組み合わせることで、より効果的にスパム攻撃を防ぐことができます。常に最新の情報を入手し、ウェブサイトのセキュリティを継続的に強化することが重要です。

まとめ:セキュリティとユーザーエクスペリエンスの両立を目指して

本記事では、Cloudflare TurnstileとSupabase Edge Functionsを用いたフォーム保護の方法を詳細に解説しました。 これらの技術を適切に活用することで、スパム対策と優れたユーザーエクスペリエンスの両立が可能になります。 本記事が、皆様のウェブサイトのセキュリティ向上に役立つことを願っています。 ご不明な点等ございましたらお気軽にお問い合わせください。