web-dev-qa-db-fra.com

Comment enregistrer les tentatives de connexion et de déconnexion réussies et échouées dans Django?

Je souhaite enregistrer toutes les tentatives de connexion et de déconnexion d'un utilisateur dans Django. Cet enregistrement doit afficher un historique de tous les utilisateurs connectés, l'adresse IP et l'heure de la connexion/déconnexion.

La table Django_admin_log semble n'enregistrer que les activités ADD/DELETE/CHANGE des autres modèles, et non un historique de l'accès des utilisateurs. J'ai également déjà vérifié les signaux user_logged_in, user_logged_out. Il semble que si je veux utiliser ces signaux, je dois créer un nouveau tableau pour enregistrer l'historique de tous les identifiants de connexion/déconnexion. Y a-t-il une méthode intégrée dans Django pour le faire? Ou des forfaits disponibles? J'ai vérifié d'autres packages et ceux liés aux tentatives de connexion limitent uniquement les tentatives infructueuses, mais n'enregistrent pas les connexions réussies.

14
ryan_2016

Vous pouvez vous connecter aux signaux fournis: Django.contrib.auth.signals

Enregistrement pour vous connecter

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

Enregistrement sur modèle/base de données

Donc, comme cette réponse n’a pas encore été acceptée - voici un exemple qui montre les actions d’un modèle au lieu de la journalisation:

Modèle

# <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',]
22
ohrstrom

J'ai une nouvelle réponse qui a été intégrée avec l'utilisateur Django (AbstractUser) comme ci-dessous:

model.py (Création d'un modèle héritant d'un utilisateur 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 (Enregistrement sur le modèle Django et se connecter):

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

[REMARQUE]: 

  • username se trouve dans l’un des champs AbstarctUser.

  • Utilisateur heure de connexion est intégré à Django AbstractUser. (Il n'est pas nécessaire que Soit mis en œuvre)

  • De même, vous pouvez implémenter login_faild de la même manière.


0
Benyamin Jafari