Cloudflare Turnstileを試してみる ついでにreCAPTCHAとの比較も

2022年9月28日、CloudflareからCAPTCHAに代わり、利便性が高く、プライバシーが守られるTurnstileが発表されました。

https://blog.cloudflare.com/ja-jp/turnstile-private-captcha-alternative-ja-jp/

今回はTurnstileを実際に試してみて、reCAPTCHAとの比較をしていきたいと思います。

# Turnstileとは
botによるWebサイト攻撃を防ぐため人間とコンピュータ(ロボット)を区別するCloudflareのWebサービスです。

同様のサービスでGoogleのreCAPTCHAも有名ですね。タイルから画像を選択するあれです。もっと前は歪んだ文字を入力するものもありました。
![スクリーンショット 2022-12-14 12.05.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742391/1388dac6-a7ac-c494-3194-ee2750584b49.png)


### bot対策しないとどうなる？

下記はあくまでも一部ですがbotによる不正利用の例になります。
- ユーザーID、パスワードをランダムに入力してログインを自動的に大量に行う
- 予約システムで支払いはせずに仮予約だけを大量に作り続ける
- レビューサイトで故意に評価を上げ下げする目的で自動的に評価をする

どうでしょうか。仮予約で座席は埋められているのに、実際の支払いはされないなど、ビジネス的にかなりの損失になりますよね。なのでこういった悪質な行為の対策が必要になってきます。

# Turnstileの使い方

まずはCloudflareのアカウントを作成してログインします。左のサイドバーのTurnstileを選択し、Add siteをクリックすると、登録画面が表示されます。
![スクリーンショット 2022-12-14 23.25.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742391/b9c14a86-79c8-921c-b7e8-a20ccd98abf0.png)

SitenameはWidgetは後からでも変更可能ですが、Domainだけは最初から入力する必要があるので、サイトは事前に用意する必要があります。reCAPTCHAはローカル環境でも使用できますが、Turnstileはできなさそうです。これはかなり不便かも、、

登録が完了するとフロントエンドで使用するSite keyとバックエンドで使用するSecret keyが表示されます。この値は後で再度確認することも可能です。Secret keyのみ変更が可能です。再度変更は2時間待つ必要があるようです。


### vue３で実装
フロントはvueで実装し、デプロイはFirebaseを利用しました。バックエンドはリクエストを送信するだけなのでPostmanで済ませてます。また今回はフォーム保護を想定して作っており、設定はベターにログイン画面です。

~~~typescript
<script setup lang="ts">
import { onMounted, reactive, ref } from "vue";

const disabled = ref(true);
const turnstileData = reactive({
  secret: "0x4AAAAAAABhogehoge",
  response: "",
});

onMounted((): void => {
  window.onloadTurnstileCallback = function () {
    turnstile.render("#turnstile-container", {
      sitekey: "0x4AAAAAA0000000000",
      callback: turnstileVerified,
    });
  };
});

const turnstileVerified = (): void => {
  turnstileData.response = turnstile.getResponse();
  disabled.value = false;
};
</script>

<template lang="pug">
h2.title Turnstile login demo
  form.form-block(method="POST" @submit.prevent="clickSubmit")
    input.input(
      type="text"
      placeholder="username"
      v-model="name"
    ) 
    input.input(
      type="email" 
      placeholder="email"
      v-model="email"       
    )
    #turnstile-container    
    button(
      type="submit"
      :disabled="disabled"
    ) ログイン  
</template>
~~~

それとheadタグにscriptタグを仕込んでください。今回は明示的にTurnstileをレンダリングしたかったので、複数のコールバック オプションを備えたグローバル関数にアクセスできる方を選びました。
~~~js
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback" async defer></script>

~~~
[公式ドキュメント](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#explicitly-render-the-turnstile-widget)



これで`turnstile.render()`をするとTurnstileのウィジェットがレンダリングされ、検証が開始されます。また検証に成功した際のコールバックが指定できます。今回の場合は成功すると予め用意していたdataに、バックエンドの検証で必要なresponseを入れ、ログインボタンのdisabledを解除するようにしました。


他のオプションとして、ウィジェットがタイムアウト、期限切れした際に利用できる`reset()`やあまり利用しないかもですが、ウィジェットをDOM要素ごと削除する`remove()`などがあるようです。


### 動作確認

フォームのある画面にアクセスするとTurnstileが自動的に検証を始めます。

![Kapture 2022-12-15 at 00.39.54.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742391/7e681f53-6abe-aa5a-e9cc-e21e67c5fe5c.gif)

検証が成功しましたね！ログインボタンも有効化されてます。

さらに取得したresponseとsecret keyをPostmanでsiteverify エンドポイントに送信します。

![スクリーンショット 2022-12-15 2.02.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742391/f382a6cd-7e0a-b89e-8df5-a7895bf32c89.png)

バックエンドで行う検証も`success: true`になりました！

いかがでしょうか、ユーザーは何もすることなく検証することができ、数行のコードで実装できるのでかなり手軽に導入できました。
ただ手軽にできても、botからのアクセスを防いでくれなければ意味がないので最後にその検証も行っていきます。

### bot検証
seleniumを動かして先ほどのページにアクセスしてみます。

![Kapture 2022-12-15 at 02.18.52.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742391/9897d2a0-a210-aaeb-35a0-f76b80987f41.gif)


ちゃんとFailureになりますね！しっかりとbotと認識しているみたいです。

## Google reCAPTCHAとの比較
Turnstileはわずかなコードの追加とHttpリクエストのみで、ユーザーに意識させることなくbot検証ができるので気軽に導入できそうです。ここからはreCAPTCHAとの比較をしていこうと思います。

#### 動作の安定性
動作で言うとTurnstileに比べてreCAPTCHAの方が安定性があるのは間違いないと思います。
というのもTurnstileはまだベータ版だからなのか、リロードを数回しないと検証が始まらないことなどが何度かありました。しばらくすると普通に検証が開始されるのですが、実用するには注意が必要かと思います。

#### 利便性
どのバージョンを利用するかによりますが、パネルを選ばせるreCAPTCHA　v2よりもTurnstileの方が利便性は高いと思います。
reCAPTCHA　v3からはページ内での行動にスコア付けし、人間かbotか判定するようになったので、ユーザーが特別な操作をしなくていいのはTurnstileと同様です。ただスコアの閾値の検討などで実装の負担がやや増える分、Turnstileが1番気軽に使えると思います。Turnstileがローカル環境でも使用できればなお便利なのですが、、、

#### その他
reCAPTCHA v3はbot検証にcookieの情報を使用しているようです。Googleは「reCAPTCHAで取得されたデータは、広告のターゲティングやユーザーの興味や関心の分析には使用しない」とアナウンスしていますが、どうなんでしょう、、、
もしcookieの取り扱いに厳しい案件でreCAPTCHA を使用する場合は注意が必要です。一方でTurnstileは検証にcookieの情報は使用していないようです。

## まとめ
今回はCloudflare Turnstileを試してみました。現状はまだベータ版ということもありreCAPTCHAを選択する方がベターかなと思います。しかし利便性が高いことは間違いないので、今後正式にリリースされれば十分bot対策の選択肢のひとつになると思います。




#### ps
今回は@39yatabis さんにお誘いいただき TLB Enjoy Developers Advent Calendar 2022 に参加しました。
自分も毎日記事が公開されるのを楽しみにしています。ぜひ他の方の記事も見てみてください🙇‍♂️

明日は @sinoguro  さんの記事です！
お楽しみに！！