如何在Django中记录成功和失败的登录和注销尝试?

时间:2016-06-03 15:40:03

标签: python django logging

我想在Django中记录所有用户登录和注销尝试。此记录应显示所有登录/注销用户的历史记录,IP地址和登录/注销时间。

django_admin_log表似乎只记录其他模型的ADD / DELETE / CHANGE活动,而不是用户访问历史记录。我还检查了user_logged_inuser_logged_out信号。似乎如果我将使用这些信号,我需要创建一个新表来记录所有用户登录/注销的历史记录。 Django中是否有内置方法来执行此操作?还是可用的套餐?我已检查过其他软件包,与登录尝试相关的软件包仅限制失败的尝试,但不记录成功的登录/注销。

2 个答案:

答案 0 :(得分:22)

您可以连接到提供的信号: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',]

答案 1 :(得分:0)

我有一个与Django用户(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字段之一中。

  • 用户登录时间是内置的Django AbstractUser。 (不需要 待实施)

  • 此外,您可以类似的方式实现 login_faild