0.はじめに
ログインや新規登録を伴うWebアプリにおいて、Botによるスパム登録や投稿は避けられないリスクです。
私が実際に作成したアプリでも大量のアカウント作成・パスワード再発行メールの濫用が起こってしまいました。
そこで、対策としてGoogle reCAPTCHA v2 を導入しました。
今回はGoogle reCAPTCHAを導入する手順について解説します。
1.起きた問題:公開アプリへのBot的アクセス
AWS EC2上にデプロイし、ドメイン取得およびHTTPSの対応を済ませていました。
しかし、WEBアプリ公開後、アカウントが意図せず複数作成されているのを検知しました。
特定ユーザーによる大量のPOSTやパスワード再発行リクエストが発生し、スパム的にタスク投稿やメール送信が繰り返される事態となりました。
この時点での問題として、Bot対策を行っていないということに気づきました。
2. 解決方針:reCAPTCHAの導入
そこで、対応として、reCAPTCHAを導入することで、Botによるアクセスを防止することにしました。
次の章で実装手順を解説します。
3. 実装手順
(1)必要パッケージのインストール
ターミナル上で下記を入力してreCAPTCHAをインストールします。
pip install django-recaptcha
(2)settings.py の設定
settings.py上にインストールしたアプリにcaptchaと記載し、パブリックキーとプライベートキーの参照箇所を記載します。
(captchaでうまく動かない場合は、バージョンや環境によってdjango_recaptchaを指定するとうまくいくことがあります。)
INSTALLED_APPS = [
...
'captcha',
]
RECAPTCHA_PUBLIC_KEY = os.getenv("RECAPTCHA_PUBLIC_KEY")
RECAPTCHA_PRIVATE_KEY = os.getenv("RECAPTCHA_PRIVATE_KEY")
参照元は.env.productionなどを用いて環境変数を管理します。
.env.productionの記載例は以下の通りです。
xxxxxxxxxxxxxxxxxxxxxxxxxxの部分に取得したキーをコピペします。
なお、""(ダブルクォーテーション)などがあったり、=との間にスペースがあったりすると読込が失敗してしまいます。
RECAPTCHA_SITE_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxx
RECAPTCHA_SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxx
(3)forms.py の改修例
下記の通り実装します。
from captcha.fields import ReCaptchaField
from captcha.widgets import ReCaptchaV2Checkbox
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
captcha = ReCaptchaField(widget=ReCaptchaV2Checkbox)
class Meta:
model = CustomUser
fields = ('username', 'email')
上記でうまくいかなければ下記の通り実装します。
# ここから
from django_recaptcha.fields import ReCaptchaField
from django_recaptcha.widgets import ReCaptchaV2Checkbox
# ここまでが上記と異なる箇所
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
captcha = ReCaptchaField(widget=ReCaptchaV2Checkbox)
class Meta:
model = CustomUser
fields = ('username', 'email')
(4)入力フォームへの実装方法
私のアプリでは、ユーザー新規登録画面及びパスワード再発行メール送信フォームにreCAPTCHAを追加しました。
ここでは、ユーザー新規登録画面(signup.html)への実装例を記載します。
{{ form.captcha }}と入力することで、記載箇所にreCAPTCHAが表示されます。
<form method="post">
{% csrf_token %}
{% include "partials/form_row.html" with field=form.username label="ユーザー名" %}
{% include "partials/form_row.html" with field=form.email label="メールアドレス" %}
{% include "partials/form_row.html" with field=form.password1 label="パスワード" %}
{% include "partials/form_row.html" with field=form.password2 label="パスワード(確認用)" %}
<div class="form-group mb-2">
{{ form.captcha }}
</div>
<div class="d-flex gap-2 align-items-center">
<button type="submit" class="btn btn-primary"><i class="fa-solid fa-user-plus"></i>登録</button>
</div>
<div class="d-flex align-items-center pt-2">
<div>アカウントをお持ちの場合:</div>
<a href="{% url 'login' %}" class="btn btn-link ps-0">ログイン</a>
</div>
</form>
(5)テンプレートへのscript追加
テンプレートの最後にこれを記述します。
この記述がないと本番環境でreCAPTCHAが表示されないので注意が必要です。
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
(6)reCAPTCHAの登録
登録は以下のページから行います(Googleアカウント必須):
https://www.google.com/recaptcha/admin/create
こちらに必要事項を入力して送信すればreCAPTCHAが使えるようになります。

4.結果と効果
reCAPTCHAを導入した結果、botによる不審なユーザー登録及びタスクの送信は止まりました。
また、ログを確認したところ、導入以降はPOSTリクエストの頻度が激減し、不審な登録・投稿は確認されていません。
ちなみに、導入後は下記の赤枠の通り、reCAPTCHAが反映されています。

5.おわりに
このように、Webアプリを本番環境に公開するだけで「標的」になり得ます。
思わぬトラブルにも見舞われないように、認証機能を伴うWebアプリを公開する際は、reCAPTCHAの導入を事前に検討しておくことを強く推奨します。