2021/02/27

NuxtJSのサイトにGoogle Recaptcha v3を導入してみました

nuxtjspythongoogle-recaptcha

概要

reCAPTCHA v3  |  Google DevelopersをNuxtJSのサイトに導入することになったのでその作業ログです。

ちゃんと人の手で、アカウント登録やパスワード忘れのリクエストがされたかをチェックしたかったので導入しました。

フロントのWebアプリはNuxtJSを採用していたため、NuxtJSで使えるライブラリ@nuxtjs/recaptchaを使わせていただきました。

バックエンドはPythonを利用しているため、Pythonで簡単なユーティリティクラスを作って認証処理を書きました。

Rechaptchaの管理コンソールなどでの設定はこの記事のscope外です。

実装内容

NuxtJS

実装内容はrecaptcha-module/example/v3 at master · nuxt-community/recaptcha-moduleが参考になりました。

Install

モジュールをインストールします。

% yarn add @nuxtjs/recaptcha

nuxt.config.js

  modules: [
    // この行を追加
    '@nuxtjs/recaptcha',
  ]
  // 以下のプロパティを追加
  recaptcha: {
    hideBadge: true,
    siteKey: process.env.GOOGLE_RECAPTCHA_SITE_KEY, // dotenvを使って、.envファイルに定義しておきます。
    version: 3,
  },

page

ページ側は以下のようになりました。

  • mountedで、$recapthcaを初期化
  • beforeDestroyで、$recapthcaを削除
  • submit時にtokenを取得して、取得したtokenを使ってapiを呼ぶ
<script>
export default {
  data() {
    return {
      email: '',
    }
  },
  async mounted() {
    try {
      await this.$recaptcha.init()
    } catch (e) {
      console.error(e)
    }
  },
  beforeDestroy() {
    this.$recaptcha.destroy()
  },
  methods: {
    async submit() {
      this.$nuxt.$loading.start()
      try {
        const token = await this.$recaptcha.execute('password_recovery')
        const data = await this.$axios.$post('/auth/password-recovery', {
          recaptcha_token: token,
          email: this.email,
        })
        console.log(data.message)
      } catch (err) {
        console.error(err)
      } finally {
        this.$nuxt.$loading.finish()
      }
    },
  },
}
</script>

Python

以下のような感じで簡単なユーティリティクラスを作ってチェックしました。

import logging
import requests

logger = logging.getLogger(__name__)


class Recaptcha:
    """ドライバークラスです。リクエストするだけ"""
    @classmethod
    def post_verify_request(cls, token):
        url = "https://www.google.com/recaptcha/api/siteverify"
        data = {"secret": "YOUR_GOOGLE_RECAPTCHA_SECRET_KEY", "response": token}
        response = requests.post(url=url, data=data)
        return response.json()


class RecaptchaService:
    """ユーティリティクラス"""
    @classmethod
    def verify(cls, token) -> bool:
        try:
            verify_result = Recaptcha.post_verify_request(token=token)
            if verify_result.get("success"):
                return True
            else:
                return False
        except Exception as e:
            logger.warning(f"Recaptcha request failed...{e}")
            return False

# RecaptchaService.verify(token)を呼び出してチェックできます。

以上になります。