【Django】ログイン試行回数制限:パスワード認証失敗時のアカウントロック(django-axes)

2022.01.01 /

【Django】ログイン試行回数制限:パスワード認証失敗時のアカウントロック(django-axes)

本記事ではDjangoで作成したWebアプリケーションに、ログインの試行回数制限を設ける方法を解説していきます。

一定回数連続でパスワード認証を失敗した場合にアカウントをロックすることは、ブルートフォース攻撃の対策になります。

アカウントロックは公開しているWebアプリケーションでは必須の機能です。本記事を通してDjangoにアカウントロック機能を追加する方法を学んでください。

ここではライブラリdjango-axesを利用します。本記事で利用するPythonなどのバージョンは以下の通りです。

  • Python:3.9.7
  • Django:4.0
  • django-axes:5.28.0

Djangoにログイン認証機能を設置する方法に関しては以下記事をご参照ください。

ログイン試行回数制限:アカウントロック機能とは

ログイン試行回数制限とは、一定回数ログインを失敗した場合にそのアカウント(IPアドレス)からログインできなくする機能です。

ログインを必要とするWebアプリケーションの場合、ログインに一定回数失敗した際にそのアカウントをロックする機能は必要になります。

アカウントをロックしてログインを何度も試みられなくすることは、ブルートフォース攻撃(総当たり攻撃)の対策になります。

ブルートフォース攻撃とは

ブルートフォース攻撃(Brute Force Attack)とは「総当たり攻撃」とも呼ばれるパスワードを解読する攻撃の1つです。

パスワードを解読するために、あらゆるパターンのパスワードを試みてパスワードを解読します。この攻撃の特徴としては時間がかかるが、いつかはパスワードを解読できるということです。

今でも実際にこの攻撃は犯罪で利用されています。

ブルートフォース攻撃を防ぐための一番の方法は、Webアプリケーション側にアカウントロック機能を組み込むことです。

ログイン試行回数制限の実装

DjangoによるWebアプリケーションにログイン試行回数制限(アカウントロック機能)を実装する流れは以下の通りです。

  1. django-axesのインストール
  2. settings.pyに設定の追加
  3. マイグレーションの実行

django-axesのインストール

ログイン試行回数制限(アカウントロック機能)を組み込むには、ライブラリdjango-axesを利用します。

まずpipコマンドでdjango-axesをインストールします。

pip install django-axes

settings.py:django-axesの追加

Djangoで「django-axes」が利用できるようにsettings.pyを編集します。

settings.pyの「INSTALLED_APPS」、「MIDDLEWARE」、「AUTHENTICATION_BACKENDS」に以下の通り設定値を追加します。

INSTALLED_APPS = [
    …
    'axes',
]

MIDDLEWARE = [
    …
    'axes.middleware.AxesMiddleware',
]

AUTHENTICATION_BACKENDS = [
    'axes.backends.AxesBackend',
    'django.contrib.auth.backends.ModelBackend',
]
注意点

「axes.backends.AxesBackend」は「django.contrib.auth.backends.ModelBackend」よりも前に追加する必要があります

マイグレーションの実行

「django-axes」で利用するテーブル(axes_accessattempt、axes_accesslog)を生成します。

管理コマンドユーティリティのmanage.pyを使ってマイグレーションを実行します。

python manage.py migrate

上記コマンドによりアカウントロック機能に必要なテーブルが生成されました。

Django:アカウントロック用のテーブル作成

アカウントロック機能の確認

実際にログインを失敗してアカウントをロックしてみましょう。

デフォルトでは3回連続で失敗することでアカウントがロックされます。アカウントがロックされると以下の文言が表示されます。

Account locked: too many login attempts. Contact an admin to unlock your account.

初期設定では接続するIPアドレスでロックを行っているため、ほかのアカウントでログインを試みても同様の文言が表示されます。

ロックされたアカウントの解除

ロックされたアカウントはデフォルトでは手動でのみ解除できます。方法は以下の3つあります。

  1. コマンドによる解除
  2. 管理サイトから解除
  3. django-axesのAPIから解除

コマンドによるアカウントロック解除

コマンドからアカウントロック解除を解除するには管理コマンドユーティリティのmanage.pyのコマンドを使用します。

すべてのアカウントロックを解除するには以下のコマンドを実行します。

python manage.py axes_reset

ロックされたアカウント名を指定してロックを解除するには以下のコマンドを実行します。

python manage.py axes_reset_username [username]

IPアドレスを指定してアカウントロックを解除するには以下のコマンドを実行します。

python manage.py axes_reset_ip [ip address]

管理サイトからアカウントロックの解除

私の場合、業務上では管理サイトからアカウントロックを解除することがほとんどです。

管理サイトからアカウントロックを解除する方法は以下の通りです。

  1. Djangoの管理サイトにログイン
  2. AXESの「Access attempts」を選択
  3. Django:管理サイトでAccess attemptsを選択
  4. 該当のレコードを選択する
  5. Django:管理サイトでAccess attemptsのレコードを選択
  6. 「Delete」を押してレコードを削除する

上記操作により、ロックされていたアカウント(IPアドレス)が解除されます。

アカウントロック機能の設定カスタマイズ

「django-axes」によるアカウントロック機能はデフォルトでは以下の設定となっています。

  • 3回の連続ログイン失敗でアカウントロック
  • IPアドレスでアカウントロックがされる
  • 自動でロックは解除されない(手動による解除が必要)
  • アカウントロック時に表示される文言が「Account locked: too many login attempts. Contact an admin to unlock your account.」

上記にあげた初期設定やそのほかの設定を細かく変更することができます。設定をカスタマイズするには設定ファイルsettings.pyを編集します。

各種カスタマイズについて解説していきます。

ログイン試行回数の制限設定

何回連続でログインを失敗するとアカウントをロックするかを設定できます。デフォルトの設定では3回でロックされるようになっています。

ログイン試行回数の設定は設定ファイルsettings.pyに「AXES_FAILURE_LIMIT」を追記します。

構文

AXES_FAILURE_LIMIT = ログイン試行回数

5回連続で失敗したらアカウントをロックしたい場合は「AXES_FAILURE_LIMIT = 5」とします。

アカウントロックの自動解除

アカウントロックが自動解除されるまでの時間を設定できます。デフォルトの設定では手動でしかロックを解除できません。

アカウントロックの自動解除の時間は設定ファイルsettings.pyに「AXES_COOLOFF_TIME」を追記します。

構文

AXES_COOLOFF_TIME = 解除されるまでの時間

指定する時間の単位は「時間」です。アカウントロックされた3時間後に解除する場合は「AXES_COOLOFF_TIME = 3」とします。

アカウントでロック

ロックする対象をアカウントに設定できます。デフォルトの設定ではIPアドレスに対してロックを行います。

ロックをアカウントにするには設定ファイルsettings.pyに「AXES_ONLY_USER_FAILURES=True」を追記します。

AXES_ONLY_USER_FAILURES = True

ログイン成功時に失敗回数のリセット

ログイン成功した際にログイン失敗の回数をリセットできるように設定できます。デフォルトの設定ではログイン成功しても失敗した回数はリセットされません。

失敗回数をリセットできるようにするには設定ファイルsettings.pyに「AXES_RESET_ON_SUCCESS=True」を追記します。

AXES_RESET_ON_SUCCESS=True

アカウントロック時の表示

アカウントロック時に表示するページを指定したテンプレートに設定できます。デフォルトでは「Account locked: too many login attempts. Contact an admin to unlock your account.」の文言が表示されます。

アカウントロック時に表示されるテンプレート設定には設定ファイルsettings.pyに「AXES_LOCKOUT_TEMPLATE」を追記します。

構文

AXES_LOCKOUT_TEMPLATE = テンプレートパス

まとめ

本記事「【Django】ログイン試行回数制限:パスワード認証失敗時のアカウントロック(django-axes)」はいかがでしたか。

django-axesを利用することで簡単にアカウントロック機能を組み込めます。ぜひWebアプリケーションに追加してみてください。