7
6

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 REST Frameworkでログイン時のアカウントロック機能を実現するクールな方法!

Posted at

概要

Django REST Frameworkとdjango-axesを使用して、ログイン試行に失敗した場合のアカウントロック(アカウント凍結)機能を実装する方法を説明します!

使用技術

pyproject.toml
python = "^3.11.2"
Django = "^4.2.7"
djangorestframework = "^3.14.0"
pydantic = "^1.10.7"
gunicorn = "^21.2.0"
django-axes = "^6.1.1"

説明する前の前提

コードの細部やDjango REST Framework自体の説明はあまりしません
また、インポートもとのコードが不要な場合は明記していません
ご了承ください🙇

django-axesとは

Djangoフレームワーク内でログイン試行の監視やアカウントロック、IPアドレスのブラックリスト等の機能を提供してくれる多機能なライブラリです

早速コードを見ていきましょう!

まずは設定から

settings.py

INSTALLED_APPS = [
    # 以下を追加 他は省略
    "axes",
]

MIDDLEWARE = [
    # 以下を追加 他は省略
    "axes.middleware.AxesMiddleware",
]

AUTHENTICATION_BACKENDS = [
    # 以下を追加
    "axes.backends.AxesBackend",
    "django.contrib.auth.backends.ModelBackend",
]

settings.pyにてdjango-axesをアプリに読み込んでもらうように各記述を追記していきましょう

environment_variable.py
from pydantic import BaseSettings


class AxesVariableSettings(BaseSettings):
    """django-axes関連の環境変数を取得する設定クラス"""

    AXES_FAILURE_LIMIT: int = 5
    """ロックされるまでのログイン回数"""
    AXES_COOLOFF_TIME: float = 1
    """自動でロックが解除されるまでの時間"""
    AXES_LOCKOUT_PARAMETERS: list = ["username"]
    """ロック対象をusernameで判断する"""
    AXES_RESET_ON_SUCCESS: bool = True
    """ログインに成功したら失敗回数をリセットする"""
    AXES_RESET_COOL_OFF_ON_FAILURE_DURING_LOCKOUT: bool = False
    """Trueの場合、ロックアウト中にログインに失敗した場合、クールオフ期間がリセット"""

例えば上記のように環境変数は設定できます
以下で指定できるオプションを確認できます

common/axes_signal.py
from axes.signals import user_locked_out
from django.dispatch import receiver
from rest_framework.exceptions import PermissionDenied


@receiver(user_locked_out)
def axes_signal(*args, **kwargs):
    raise PermissionDenied("アカウントは凍結されてるよ。ちょっと待ってね")

ライブラリが提供するuser_locked_out シグナルをキャッチし、そのイベントが発生した際に特定の処理を実行するためのものです

app/apps.py
from django.apps import AppConfig


class ApplicationConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "app"

    def ready(self):
        from common import axes_signal

ready メソッドは、アプリケーションが起動したときに実行される初期化コードを提供します。この特定の ready メソッドでは、axes_signal 関数をインポートしています

特に、user_locked_out シグナルが発生したときに、アカウントが凍結されたことを示すメッセージを含んだ PermissionDenied 例外を発生させます

準備は整いました!!動きを確認してみましょう🔥

アカウントロック状態はaccess_attemptテーブルで管理されています
今は何もレコードがありません

image.png

1回ログインに失敗するとレコードが生成されます
failures_since_startが1となっています
image.png

5回失敗してみました
これでfailures_since_startが5回となり、先ほど設定した失敗した旨のエラーレスポンスが返却されます
この状態で正しいユーザーID、パスワードでログインしようとしても凍結されているのエラーが返ってきます👍
image.png

AXES_COOLOFF_TIMEで指定した時間が経過するか、該当レコードを削除すると
アカウントロックは解除されます

なので、アカウントロック解除機能を実現するには該当のレコードを指定して、削除すれば実装できます

最後に

流れさえ、抑えればスムーズに開発が進められると思います🐰
アカウントロック機能について説明されている記事は少なかったので参考になれば嬉しいです
ぜひ、お試しを!

7
6
0

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
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?