web-dev-qa-db-ja.com

ログインとログアウトの成功と失敗の両方をDjangoに記録するにはどうすればよいですか?

Djangoでのすべてのユーザーログインとログアウトの試行を記録したいと思います。このレコードには、ログイン/ログアウトしたすべてのユーザーの履歴、IPアドレス、ログイン/ログアウトの時間が表示されます。

Django_admin_logテーブルは、他のモデルのADD/DELETE/CHANGEアクティビティのみを記録し、ユーザーアクセスの履歴は記録しないようです。また、user_logged_inuser_logged_outの信号も確認しました。これらの信号を使用する場合、すべてのユーザーのログイン/ログアウトの履歴を記録する新しいテーブルを作成する必要があるようです。 Djangoこれを行うための組み込みメソッドはありますか?または利用可能なパッケージ?他のパッケージをチェックしましたが、ログイン試行に関連するものは失敗した試行のみを制限しますが、記録しません成功したログイン/ログアウト。

17
ryan_2016

提供されたシグナルにフックすることができます: Django.contrib.auth.signals

ログに記録

import logging
from Django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from Django.dispatch import receiver

log = logging.getLogger(__name__)

@receiver(user_logged_in)
def user_logged_in_callback(sender, request, user, **kwargs):    
    # to cover more complex cases:
    # http://stackoverflow.com/questions/4581789/how-do-i-get-user-ip-address-in-Django
    ip = request.META.get('REMOTE_ADDR')

    log.debug('login user: {user} via ip: {ip}'.format(
        user=user,
        ip=ip
    ))

@receiver(user_logged_out)
def user_logged_out_callback(sender, request, user, **kwargs): 
    ip = request.META.get('REMOTE_ADDR')

    log.debug('logout user: {user} via ip: {ip}'.format(
        user=user,
        ip=ip
    ))

@receiver(user_login_failed)
def user_login_failed_callback(sender, credentials, **kwargs):
    log.warning('logout failed for: {credentials}'.format(
        credentials=credentials,
    ))

モデル/データベースへの記録

したがって、この回答はこれまで受け入れられていなかったため、ログの代わりにモデルのアクションを痛める例を次に示します。

型番

# <your_app>/models.py

from Django.db import models
from Django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from Django.dispatch import receiver


class AuditEntry(models.Model):
    action = models.CharField(max_length=64)
    ip = models.GenericIPAddressField(null=True)
    username = models.CharField(max_length=256, null=True)

    def __unicode__(self):
        return '{0} - {1} - {2}'.format(self.action, self.username, self.ip)

    def __str__(self):
        return '{0} - {1} - {2}'.format(self.action, self.username, self.ip)


@receiver(user_logged_in)
def user_logged_in_callback(sender, request, user, **kwargs):  
    ip = request.META.get('REMOTE_ADDR')
    AuditEntry.objects.create(action='user_logged_in', ip=ip, username=user.username)


@receiver(user_logged_out)
def user_logged_out_callback(sender, request, user, **kwargs):  
    ip = request.META.get('REMOTE_ADDR')
    AuditEntry.objects.create(action='user_logged_out', ip=ip, username=user.username)


@receiver(user_login_failed)
def user_login_failed_callback(sender, credentials, **kwargs):
    AuditEntry.objects.create(action='user_login_failed', username=credentials.get('username', None))

管理者

# <your_app>/admin.py
from Django.contrib import admin
from models import AuditEntry

@admin.register(AuditEntry)
class AuditEntryAdmin(admin.ModelAdmin):
    list_display = ['action', 'username', 'ip',]
    list_filter = ['action',]
29
ohrstrom

以下のようにDjango user(AbstractUser)と統合された新しい回答があります。

model.py(Djangoユーザーから継承するモデルの作成):

from Django.contrib.auth.models import AbstractUser
from Django.db import models

class UserModel(AbstractUser):  # Inherit from Django user
    last_logout = models.DateTimeField(null=True, blank=True)
    status = models.CharField(max_length=64)
    ip = models.GenericIPAddressField(null=True)

    def __str__(self):
        return '{} - {}'.format(self.username, self.ip)

Signal.py(Djangoモデルへの記録とログ):

from Django.contrib.auth.signals import user_logged_out
from Django.dispatch import receiver
from Django.utils import timezone
from <model> import UserModel  # above model
from logging import getLogger

logger = getLogger(__name__)

def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip


@receiver(user_logged_out)
def user_logged_out_callback(sender, request, user, **kwargs):
    ip = get_client_ip(request)
    username = request.user.username  # get the username.
    now = timezone.now()
    logger.warn('{} logged out with {} IP'.format(user, ip))  # recording to log
    UserModel.objects.filter(username=username).update(last_logout=now,
                                                   status='user_logged_out',
                                                   ip=ip
                                                   )  # recording to the model

[[〜#〜]ノート[〜#〜]]:

  • usernameは、AbstarctUserフィールドの1つにあります。

  • ユーザーログイン時間は組み込みDjango AbstractUser。(実装する必要はありません)

  • また、同様の方法でlogin_faildを実装できます。


0
Benyamin Jafari