2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DjangoアプリにreCAPTCHAを導入してスパム対策した話

Last updated at Posted at 2025-07-05

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を指定するとうまくいくことがあります。)

settings.py
INSTALLED_APPS = [
    ...
    'captcha',
]

RECAPTCHA_PUBLIC_KEY = os.getenv("RECAPTCHA_PUBLIC_KEY")
RECAPTCHA_PRIVATE_KEY = os.getenv("RECAPTCHA_PRIVATE_KEY")

参照元は.env.productionなどを用いて環境変数を管理します。
.env.productionの記載例は以下の通りです。
xxxxxxxxxxxxxxxxxxxxxxxxxxの部分に取得したキーをコピペします。
なお、""(ダブルクォーテーション)などがあったり、=との間にスペースがあったりすると読込が失敗してしまいます。

.env.production
RECAPTCHA_SITE_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxx
RECAPTCHA_SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxx

(3)forms.py の改修例

下記の通り実装します。

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')

上記でうまくいかなければ下記の通り実装します。

forms.py
# ここから
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が表示されます。

signup.html
<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が表示されないので注意が必要です。

base.html
<script src="https://www.google.com/recaptcha/api.js" async defer></script>

(6)reCAPTCHAの登録

登録は以下のページから行います(Googleアカウント必須):
https://www.google.com/recaptcha/admin/create

こちらに必要事項を入力して送信すればreCAPTCHAが使えるようになります。
image.png

4.結果と効果

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

ちなみに、導入後は下記の赤枠の通り、reCAPTCHAが反映されています。
image.png

5.おわりに

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

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?