Cloudflare Turnstileでサイトをbotから守る
きっかけ
以前にNext.jsでSSRを使わずに画像最適化と多言語化をしてみたという記事で解説したのですが、当サイトでは多言語化を実施することで海外からのアクセスも増えました。
ただ、残念なことにbotに見つかる頻度も上がってしまったようで、お問い合わせフォームにスパムの投稿が増えてしまいました。
当サイトはSSGで静的サイトとしてエクスポートしており、また、お問い合わせフォームはサイトからほぼ独立しているため、セキュリティリスク自体は低い方です。
それでもスパムの投稿が増えてしまうのは望ましくないため、対策することにしました。
Cloudflare Turnstile
お問い合わせフォームの認証ではGoogle reCAPTCHAが有名ですが、今回はCloudflare Turnstileを使用します。
Turnstileは、Cloudflareが提供するユーザーフレンドリーでプライバシー重視なCAPTHCAの代替手段です。
現在はベータ版が公開されており、月100万回呼び出しまで無料で使うことができます。
私はCloudflareのサービスを日頃から信頼しているので、今回はこちらを使用してみることにしました。
実装方法
サイトキーとシークレットキーの取得
Cloudflareのダッシュボードでサイトキーとシークレットキーを取得しましょう。
メニューバーの「Turnstile」から「サイトを追加」で対象のサイトを追加します。
そうすると、サイトキーとシークレットキーが表示されます。
(後でもう一度表示できるのでメモする必要はありません)
フロントエンドの実装
WebサイトにTurnstileのウィジェットを追加します。
今回はNext.js製のサイトに埋め込むので、react-turnstileというライブラリを使用します。
ターミナルでnpm i @marsidev/react-turnstile
と入力してインストールし、DocsのExamplesに従ってウィジェットの追加とフォームへの組み込みを行います。
Turnstile
コンポーネントをフォームに追加し、そこから得られたtokenをサーバーサイド側にPOSTします。
サーバーサイドの実装
DocsのExamplesやCloudflareの公式ドキュメントを参考に実装します。
フロントからPOSTされたtokenとシークレットキーをCloudflare TurnstileのエンドポイントにPOSTします。
結果のsuccess
プロパティがtrue
ならば認証に成功しているので、その後の処理を記述します。
使ってみた感想
概観
無料でサクッと実装できて非常に便利だと感じました。
また、react-turnstileの方も特にトラブルなく機能しました。
reCAPTHA v3のように明示的な認証を行わず裏で認証するようにも設定できるので、認証に失敗したり面倒なパズルを解かされたりするストレスが無く、ユーザー体験も非常によいと思います。
エラーについて
ただ、認証が若干厳しいかなとも感じました。
例えば、フォームを送信したあとにミスに気付いて再度送信したような場合、2回目の投稿がtimeout-or-duplicate
として認証に失敗することがありました。
結果のerror-codes
プロパティで上記のエラーが出たら処理を分岐させるなど、何らかの対策は必要かもしれません。
Cloudflareのダッシュボードでは認証の通過率がモニタリングできますので、定期的に確認することが重要だと思います。