1

I've implemented a model that uses django.contrib.auth.singals to record user login/logout events. The model originates from an answer given here: How can I log both successful and failed login and logout attempts in Django?

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
from __future__ import unicode_literals

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

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

    class Meta:
        db_table = "db_audit_entry"
        verbose_name = "Audit Entry"
        verbose_name_plural = "Audit Entries"

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

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

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

I also have SESSION_EXPIRE_AT_BROWSER_CLOSE set to True in settings.py.

When a user closes their web browser before logging out, a logout AuditEntry object is created with the correct action, ip address, and date. However, the username is not recorded. I don't understand why credentials does not include username when a logout event occurs due to a session expiration.

According to the Django docs for login/logout signals, username is None when a user is not authenticated, which I think means that the order of events is:

1) The session data for the user expires and the user is now de-authenticated

2) Django logs out what is now an unknown/anonymous user

Why does this happen and is there a way to preserve the username when this type of logout event occurs?

mehve
  • 36
  • 6

0 Answers0