はじめに
Webアプリのセキュリティ対策として、スパムや不正ログインを防ぐ仕組みは欠かせません。長年の定番は Google reCAPTCHA でしたが、実際に使ってみると「画像パズルを解かされる煩わしさ」や「Google によるトラッキング懸念」がつきまといます。ユーザー体験を損なうこともしばしばあり、特に商用サービスでは離脱につながる要因になりかねません。
そこで注目されているのが Cloudflare Turnstile です。Cloudflare アカウントさえあれば無料で利用でき、ユーザーにほぼ負担をかけないシンプルな動作が特徴。2022 年にリリースされて以来、「reCAPTCHA の代替」として多くの開発者から支持を集めています。
本記事では、Rails と Laravel それぞれのログインフォームに Turnstile を組み込む方法 を、実際のコード付きで解説します。reCAPTCHA から移行したい人や、新規にセキュリティを導入したい人に役立つ実践ガイドです。
Cloudflare Turnstile とは?
Cloudflare Turnstile は、Cloudflare が提供する 無料の CAPTCHA 代替サービス です。
特徴まとめ
- 無料で使える:商用利用も追加料金なし
- ユーザーフレンドリー:画像認証や文字入力なし、クリック1回か完全自動で判定
- プライバシーファースト:トラッキングを行わず、GDPR 等の規制にも配慮
- 柔軟な導入方法:シンプルな JavaScript 埋め込みと API 検証で完結
仕組み
- フォームを開くと、ユーザーのブラウザが Cloudflare に対して検証をリクエスト
- Cloudflare は「このアクセスが正規のユーザーか」を独自の仕組みで判定し、トークンを発行
- サーバー側でそのトークンを Cloudflare API に送信し、最終的な検証を実施
この仕組みにより、ユーザーは「画像パズル」や「文字入力」から解放されます。ユーザー体験を崩さずにセキュリティを確保できる のが最大の強みです。
Rails 編|Deviseログインフォームに導入する
1. Cloudflare Dashboard でキーを取得
- Cloudflare Dashboard にログイン
- 「Turnstile」メニューから新規サイトを追加
- サイトキー (
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からの移行先として最適」と言えるでしょう。
コメント