reCAPTCHAからの移行にも最適!Cloudflare TurnstileをRailsとLaravelで使う方法

技術

はじめに

Webアプリのセキュリティ対策として、スパムや不正ログインを防ぐ仕組みは欠かせません。長年の定番は Google reCAPTCHA でしたが、実際に使ってみると「画像パズルを解かされる煩わしさ」や「Google によるトラッキング懸念」がつきまといます。ユーザー体験を損なうこともしばしばあり、特に商用サービスでは離脱につながる要因になりかねません。

そこで注目されているのが Cloudflare Turnstile です。Cloudflare アカウントさえあれば無料で利用でき、ユーザーにほぼ負担をかけないシンプルな動作が特徴。2022 年にリリースされて以来、「reCAPTCHA の代替」として多くの開発者から支持を集めています。

本記事では、Rails と Laravel それぞれのログインフォームに Turnstile を組み込む方法 を、実際のコード付きで解説します。reCAPTCHA から移行したい人や、新規にセキュリティを導入したい人に役立つ実践ガイドです。


Cloudflare Turnstile とは?

Cloudflare Turnstile は、Cloudflare が提供する 無料の CAPTCHA 代替サービス です。

特徴まとめ

  • 無料で使える:商用利用も追加料金なし
  • ユーザーフレンドリー:画像認証や文字入力なし、クリック1回か完全自動で判定
  • プライバシーファースト:トラッキングを行わず、GDPR 等の規制にも配慮
  • 柔軟な導入方法:シンプルな JavaScript 埋め込みと API 検証で完結

仕組み

  1. フォームを開くと、ユーザーのブラウザが Cloudflare に対して検証をリクエスト
  2. Cloudflare は「このアクセスが正規のユーザーか」を独自の仕組みで判定し、トークンを発行
  3. サーバー側でそのトークンを Cloudflare API に送信し、最終的な検証を実施

この仕組みにより、ユーザーは「画像パズル」や「文字入力」から解放されます。ユーザー体験を崩さずにセキュリティを確保できる のが最大の強みです。


Rails 編|Deviseログインフォームに導入する

1. Cloudflare Dashboard でキーを取得

  1. Cloudflare Dashboard にログイン
  2. 「Turnstile」メニューから新規サイトを追加
  3. サイトキー (sitekey) とシークレットキー (secret) を取得

2. フロントエンドにウィジェットを埋め込む

app/views/devise/sessions/new.html.erb に以下を追加:

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="<%= ENV['TURNSTILE_SITE_KEY'] %>"></div>

3. サーバー側で検証処理を追加

app/services/turnstile_verifier.rb を作成:

require 'net/http'
require 'json'

class TurnstileVerifier
  VERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify".freeze

  def self.verify(token)
    uri = URI(VERIFY_URL)
    res = Net::HTTP.post_form(uri, {
      "secret"   => ENV["TURNSTILE_SECRET_KEY"],
      "response" => token
    })
    JSON.parse(res.body)["success"]
  end
end

4. Devise コントローラに組み込む

app/controllers/users/sessions_controller.rb

class Users::SessionsController < Devise::SessionsController
  def create
    unless TurnstileVerifier.verify(params["cf-turnstile-response"])
      flash[:alert] = "CAPTCHA verification failed."
      redirect_to new_user_session_path and return
    end
    super
  end
end

routes.rb

devise_for :users, controllers: {
  sessions: "users/sessions"
}

Laravel 編|認証フォームに導入する

1. 環境変数と設定を追加

.env

TURNSTILE_SITE_KEY=your_site_key
TURNSTILE_SECRET_KEY=your_secret_key

config/services.php

'turnstile' => [
    'sitekey' => env('TURNSTILE_SITE_KEY'),
    'secret' => env('TURNSTILE_SECRET_KEY'),
],

2. フロントエンドに埋め込む

resources/views/auth/login.blade.php のフォームに追加:

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="{{ config('services.turnstile.sitekey') }}"></div>

3. サービスクラスで検証

app/Services/TurnstileService.php

<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;

class TurnstileService
{
    public function verify($token): bool
    {
        $response = Http::asForm()->post(
            'https://challenges.cloudflare.com/turnstile/v0/siteverify',
            [
                'secret' => config('services.turnstile.secret'),
                'response' => $token,
            ]
        );

        return $response->json('success') === true;
    }
}

4. コントローラに組み込む

app/Http/Controllers/Auth/LoginController.php

public function login(Request $request, TurnstileService $turnstile)
{
    if (! $turnstile->verify($request->input('cf-turnstile-response'))) {
        return back()->withErrors(['captcha' => 'CAPTCHA verification failed.']);
    }

    return $this->traitLogin($request); // 元のログイン処理
}

ローカル開発環境での利用

Turnstile には テストモード が用意されており、開発中も安心です。

  • Always Pass モード:常に成功を返す
  • Always Fail モード:常に失敗を返す

E2E テストや QA 環境での確認に便利です。さらに「事前クリアランス Cookie」を使えば、CAPTCHA を通過した状態を擬似的に再現できます。
開発時は本番キーではなく テスト用キー を設定しておくとトラブルを避けられます。


CSP (Content Security Policy) とは?

CSP は「どの外部リソースを読み込めるか」を制御するセキュリティヘッダです。
Turnstile を使う場合、https://challenges.cloudflare.com を許可する必要があります。

Rails の場合(config/initializers/content_security_policy.rb)

policy.script_src :self, "https://challenges.cloudflare.com"
policy.frame_src  :self, "https://challenges.cloudflare.com"

Laravel の場合

spatie/laravel-csp などのパッケージを導入して同様に設定可能。

もし CSP 設定を忘れると、Turnstile ウィジェットが表示されない・通信が失敗する などの不具合が発生します。


まとめ|Rails / Laravel 導入比較

Cloudflare Turnstile は、reCAPTCHA に代わるセキュリティソリューションとして非常に有力です。

  • Rails では Service クラス + Devise コントローラに組み込み
  • Laravel では Service クラス + LoginController に組み込み
  • 共通点:フロントでウィジェット埋め込み → サーバー側で API 検証 → CSP 設定必須

特にログインフォームや新規登録、問い合わせフォームなど、攻撃を受けやすい箇所に導入するのがおすすめです。
無料で使え、UX を損なわず、プライバシーにも配慮されている点からも「reCAPTCHAからの移行先として最適」と言えるでしょう。

コメント

タイトルとURLをコピーしました