Filament 5にCloudflare Turnstileを導入するComposerパッケージ「eii/filament-turnstile」を公開しました
Laravel / Filamentを使って開発していると、ログイン画面や登録フォームなどにスパム・ボット対策を追加したくなることがあります。
そのような場面で便利なのが、Cloudflareが提供する Turnstile です。
今回は、Filament 5のフォームや認証ページにCloudflare Turnstileを簡単に導入できるComposerパッケージを作成・公開しました。
eii/filament-turnstile
- Packagist: https://packagist.org/packages/eii/filament-turnstile
- GitHub: https://github.com/amit-eiitech/eii-filament-turnstile
1. Cloudflare Turnstileとは?
Cloudflare Turnstileは、Webサイトへのボットや自動化された不正アクセスを防ぐためのCAPTCHAソリューションです。
従来のCAPTCHAでは、ユーザーに画像を選択させたり、文字を入力させたりする必要がありました。
Turnstileは、ユーザーに余計な操作を求めずに認証を行えるため、ユーザー体験を損ないにくいというメリットがあります。
今回は、このTurnstileをFilament 5のフォームで利用できるようにしました。
2. eii/filament-turnstileの主な機能
このパッケージでは、主に以下の機能を提供しています。
- 再利用可能なFilamentフォームコンポーネント
- Cloudflare Siteverify APIによるサーバーサイド検証
- Login / Registration / Password Reset用の認証ページ生成コマンド
- フォームごとに異なるAction名を設定可能
- Hostnameの許可リストによる検証
- テーマや表示方法などのカスタマイズ
- 既存のFilament認証ページを無理に置き換えずに導入できる設計
特に、既存の認証ページを利用しているプロジェクトでも、必要に応じて独自の認証ページを生成できるようにしています。
3. インストール
Composerからインストールできます。
composer require eii/filament-turnstile
LaravelのPackage Auto-Discoveryに対応しているため、Service Providerを手動登録する必要はありません。
4. Cloudflare Turnstileの設定
まず、CloudflareのダッシュボードからTurnstileのサイトを登録し、Site KeyとSecret Keyを取得します。
設定ファイルを公開します。
php artisan vendor:publish --tag=filament-turnstile-config
.env に以下を設定します。
TURNSTILE_SITE_KEY=your-site-key
TURNSTILE_SECRET_KEY=your-secret-key
TURNSTILE_ALLOWED_HOSTNAMES=yourdomain.com
TURNSTILE_ALLOW_MISSING_ACTION=false
TURNSTILE_ALLOWED_HOSTNAMES には、許可するホスト名を指定します。複数のホスト名を指定する場合はカンマ区切りです。
TURNSTILE_ALLOWED_HOSTNAMES=example.com,admin.example.com
注意点として、Hostnameの許可リストは必須です。空の場合は検証が拒否される設計になっています。
また、本番環境では TURNSTILE_ALLOW_MISSING_ACTION=false の設定を推奨します。
5. Filamentフォームへの導入
基本的な使い方は非常にシンプルです。
まず、コンポーネントをインポートします。
use Eii\FilamentTurnstile\Forms\Components\Turnstile;
あとは通常のFilamentフォームに追加するだけです。
use Filament\Schemas\Schema;
use Eii\FilamentTurnstile\Forms\Components\Turnstile;
public function form(Schema $schema): Schema
{
return $schema->components([
// Other form fields...
Turnstile::make('turnstile_token')
->label('Security Verification')
->turnstileAction('admin-users-create')
->theme('auto')
->size('normal')
->appearance('interaction-only'),
]);
}
これだけでフォームにTurnstileを追加できます。
トークンは必須項目として扱われ、フォーム送信時にはCloudflareのSiteverify APIを利用してサーバーサイドで検証されます。
フロントエンド側のコールバックだけを信用する設計にはしていません。
6. 認証ページへの導入
今回のパッケージで特に便利にしたかった機能の一つが、Filamentの認証ページへの導入です。
以下のArtisanコマンドを用意しています。
ログインページ
php artisan make:filament-turnstile-login
ユーザー登録ページ
php artisan make:filament-turnstile-register
パスワードリセット申請ページ
php artisan make:filament-turnstile-request-password-reset
これらのコマンドを実行すると、Turnstileに対応した認証ページのクラスが生成されます。
生成されるクラスは以下のとおりです。
App\Filament\Pages\Auth\
TurnstileLogin.php
TurnstileRegister.php
TurnstileRequestPasswordReset.php
生成したページはPanel Providerの認証設定に登録して利用できます。
例えば、ログインページの場合は以下のようになります。
->login(\App\Filament\Pages\Auth\TurnstileLogin::class)
既存の認証ページを無条件に上書きするのではなく、必要なページだけを生成して利用できるようにしています。
既存のカスタム認証ページを使っている場合も、無理に既存実装を置き換える必要はありません。
7. Action-aware Validation
このパッケージでこだわった機能の一つが、Action-aware Validationです。
例えば、同じCloudflare TurnstileのSite KeyとSecret Keyを使用していても、フォームごとに異なるAction名を設定できます。
'actions' => [
'login' => 'admin-login',
'register' => 'admin-register',
'request_password_reset' => 'admin-password-reset-request',
],
これにより、ログイン・ユーザー登録・パスワードリセットなど、それぞれの処理を区別できます。
さらに、サーバーサイドで期待するAction名と検証結果を照合することで、別のフォームで発行されたトークンが不適切に再利用されることを防ぎます。
Cloudflareの分析画面でも、Actionごとにトラフィックを区別しやすくなります。
独自のフォームでも同様に設定できます。
Turnstile::make('turnstile_token')
->turnstileAction('admin-users-create');
8. セキュリティについて
セキュリティ関連の機能なので、フロントエンドだけでなくサーバーサイドの検証も重視しています。
このパッケージでは、以下のチェックを実装しています。
- Cloudflare Siteverify APIによるサーバーサイド検証
- 無効なトークンの拒否
- トークンの欠落や過大なサイズのチェック
- Hostnameの許可リスト検証
- 期待するAction名との照合
- API通信や設定に問題がある場合のFail-Closed動作
- Secret Keyやトークンをログに記録しない設計
特に重要なのはFail-Closedです。
Cloudflareとの通信に失敗した場合や、必要な設定が不足している場合に、検証を通過させるのではなく、処理を拒否する設計にしています。
9. ローカル環境でのテスト
開発環境で実際のCloudflareアカウントを使わずにテストしたい場合、Cloudflareが提供している公式テストキーを利用できます。
例えば、常に検証が成功する組み合わせです。
TURNSTILE_SITE_KEY=1x00000000000000000000AA
TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA
TURNSTILE_ALLOWED_HOSTNAMES=example.com
TURNSTILE_ALLOW_MISSING_ACTION=true
テストキーを利用した場合、Cloudflareから返されるHostnameやActionもテスト用の値になります。
そのため、ローカルテスト時には許可ホスト名やActionの設定にも注意してください。
その他のテストキーについては、Cloudflareの公式ドキュメントを参照してください。
10. 動作環境
現在のパッケージの対応環境は以下のとおりです。
| 項目 | 対応バージョン |
|---|---|
| PHP | 8.2以上 |
| Laravel | 11.28以上 / 12 / 13 |
| Filament Forms | 5.x |
11. 最後に
今回のパッケージは、日々のLaravel / Filament開発で繰り返し実装することになる機能を、できるだけ簡単に再利用できるようにしたいという考えから開発しました。
特に、認証ページへの導入やサーバーサイド検証など、実際のプロジェクトで必要になる部分を意識して設計しています。
まだ改善できる部分もあると思いますので、実際に利用していただいた方からのフィードバックやご提案も歓迎しています。
もしFilament 5を利用している方がいれば、ぜひ試してみてください!
Package: https://packagist.org/packages/eii/filament-turnstile
GitHub: https://github.com/amit-eiitech/eii-filament-turnstile
開発:Eii Tech Solutions