How can I log both successful and failed login and logout attempts in Django?

前端 未结 2 1792
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-31 18:51

I want to record all user login and logout attempts in Django. This record should show a history of all users who logged in/out, IP address and time of login/logout.

The

相关标签:
2条回答
  • 2021-01-31 19:23

    You could hook up to the provided signals: django.contrib.auth.signals

    Recording to log

    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('login failed for: {credentials}'.format(
            credentials=credentials,
        ))
    

    Recording to model/database

    So as this answer has not been accepted so far - here an example that sores the actions in a model instead of logging:

    Model

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

    Admin

    # <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',]
    
    0 讨论(0)
  • 2021-01-31 19:29

    I have a new answer that has been integrated with Django user (AbstractUser) as below:

    model.py (Creating a model that inherits from Django user):

    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 (Recording to Django-model and to log):

    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
    

    [NOTE]:

    • username is located in one of the AbstarctUser fields.

    • User login time is built-in Django AbstractUser. (Do not need to be implemented)

    • Also, you can implement login_faild in a similar way.


    0 讨论(0)
提交回复
热议问题