【Vue.js】Vue3にreCAPTCHA v2を導入 【vue-recaptcha】

# 今回のゴール
VueアプリケーションにreCAPTCHA v2を導入し機能させること。

# reCAPTCHAとは
Googleが提供している、自動化されたbotやスパムからサイトを保護するセキュリティサービスです。
決済画面などでよく見かける、9枚の画像の中から条件に一致する画像を選択させられるものですね。

https://www.google.com/recaptcha/about/

# reCAPTCHA 導入手順

1. reCAPTCHAを導入するサイト登録
2. vue-recaptchaのインストールと有効化
3. イベント処理実装


### 1. reCAPTCHAを導入するサイト登録

Google reCAPTCHAにアクセスして導入するサイトの登録を行います。

https://www.google.com/recaptcha/admin/create

- reCAPTCHA タイプ
    -  `チャレンジ(v2)` を選択
- ドメイン
    - サイトのドメインは複数登録可能なので、すべて環境のドメインを登録します。 開発に使用する`ngrok`などのドメインも登録可能です。

上記の設定の送信が完了したら、サイトキーが表示されます。サイトキーをコピペしたら完了です。



### 2.Vue3にvue-recaptchaをインストール

reCAPTCHAの導入にあたって、今回は`vue-recaptcha` というライブラリを使用します。

https://github.com/DanSnow/vue-recaptcha

Vue用のreCAPTCHAライブラリは他にも存在しますが、こちらのライブラリは導入もスムーズで継続的に開発が進められているため採用しています。

今回はチェックボックス有りのv2を使用するため、リポジトリのmasterブランチを参照しています(2024/01/20時点)
開発者によると現在v3を開発中なので、参照する際は適切なブランチを選択してください。


プロジェクトにvue-recaptchaのインストールを行います。

```terminal
yarn add vue-recaptcha
```
インストールが完了したら、main.tsにて`vue-recaptcha`の有効化を行います。
下記のように記述することで、Vueインスタンス作成時にVueRecaptchaプラグイン渡すことで`vue-recaptcha`が利用可能となります。

```vue
<script>
import { createApp } from 'vue'
import App from '@/App.vue'
import { VueRecaptcha } from 'vue-recaptcha'

const app = createApp(App)
app
  .use(router)
  .component('vue-recaptcha', VueRecaptcha)
  .mount('#app')
</script>
```

 次に`vue-recaptcha`コンポーネントの読み込みを行います

```vue
<script>
import {ref} from 'vue'
import { VueRecaptcha } from 'vue-recaptcha'
const reCAPTCHA_SITE_KEY = import.meta.env.VITE_reCAPTCHA_SITE_KEY
...
</script>
```

###  3. vue-recaptcha イベント処理実装
`vue-recaptcha`イベント処理の実装を行います。

下記はvue-recapthcaで提供されているカスタムイベント一覧です。
```
verify(response) – Emit on reCAPTCHA verified response is the successful reCAPTCH response

expired() – Emit on reCAPTCHA expired

render(id) – Emit on reCAPTCHA mounted on DOM id is the widget id of the component

error() – Emit when reCAPTCHA encounters an error
```

今回は`verify`と`expired`イベントを使用して、reCAPCHAのチャレンジに成功したらボタン活性化させるように実装します。

- `expired`イベントは、reCAPTCHAのトークンが期限切れになったときに発火します。
Google reCAPTCHAの仕様上、ユーザーがチェックボックスをクリックしてからトークンが期限切れになるまでの時間は通常約2分ほどとされています。

- `verify`イベントは、ユーザーが`reCAPTCHAチャレンジ`に正常に回答し、そしてその回答がGoogleのサーバーによって検証されたときに発火するイベントです。
今回では、ユーザーが人間であることを確認した後の追加のアクションをトリガーとして使用しています。

```typescript
<script setup lang="ts">
import { ref } from 'vue'

const isVerify = ref<boolean>(false)
const verified = (response: string) => {
  //検証に成功した場合にreCAPTCHAトークンが返却される
  if (response) {
    isVerify.value = true
  } else {
    isVerify.value = false
  }
}

const expired = () => {
  isVerify.value = false
}
</script>
```

```vue
<template>
  <vue-recaptcha
    :sitekey="RECAPTCHA_SITE_KEY"
    @verify="verified"
    @expired="expired"
  ></vue-recaptcha>
</template>
```
最後にスタイルやイベント処理の修正を行ったら完了です。

- 完成画面
![qiita_recapcha (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739783/fc7ac1f6-9fd7-ec2f-417d-a09351a812ec.gif)


- 有効期限が切れた場合
![recapthca_expired](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739783/da4687b9-72fa-5dd4-7ccd-71a0b81c138d.png)


# あとがき

reCAPTCHAの導入は一見複雑に見えるかもしれませんが、vue-recaptchaの活用によりVueアプリケーションへスムーズに組み込むことが可能になります。
今回はreCAPTCHA v2を紹介しましたが、GoogleはreCAPTCHAはv2だけでなく、v3も提供しています。
v3はユーザーの行動をバックグラウンドで分析し、スコア形式でbotを検出するため、チェックボックスや画像認証チャレンジを要求せずにセキュリティチェックが可能です。このため、ユーザー体験に影響を与えることなく、セキュリティチェックを行える点で、v3は特に優れていると言えます。
今後は、v3の実装検証や他のCAPTHCAサービスとの比較検討を進めていく予定です。
最後までお読みいただき、ありがとうございました。