Django 记录 user_login_failed 信号的用户 IP

Posted

技术标签:

【中文标题】Django 记录 user_login_failed 信号的用户 IP【英文标题】:Django log user IP for user_login_failed signal 【发布时间】:2015-05-02 15:32:25 【问题描述】:

我想在我的 Django 应用程序中记录用户 IP 地址,专门用于登录、注销和登录失败事件。我正在使用 Django 内置函数如下:

from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from ipware.ip import get_ip
import logging

logger = logging.getLogger(__name__)

def log_logged_in(sender, user, request, **kwargs):
    logger.info("%s User %s successfully logged in" % (get_ip(request), user))

def log_logged_out(sender, user, request, **kwargs):
    logger.info("%s User %s successfully logged out" % (get_ip(request), user))

def log_login_failed(sender, credentials, **kwargs):
    logger.warning("%s Authentication failure for user %s" % ("...IP...", credentials['username']))

user_logged_in.connect(log_logged_in)
user_logged_out.connect(log_logged_out)
user_login_failed.connect(log_login_failed)

问题是我还没有找到获取user_login_failed 信号IP 的方法,因为这个函数的参数(https://docs.djangoproject.com/en/1.7/ref/contrib/auth/#module-django.contrib.auth.signals)中没有requestcredentials 参数是只包含usernamepassword 字段的字典。

我怎样才能得到这个信号的 IP 地址?

非常感谢您的帮助。

【问题讨论】:

【参考方案1】:

不幸的是user_login_failed singal 没有将请求作为参数传递。

结帐django-axes — https://github.com/django-pci/django-axes/

它使用自定义视图装饰器来跟踪失败的登录。

https://github.com/django-pci/django-axes/blob/master/axes/decorators.py#L273

【讨论】:

【参考方案2】:

我刚刚发现在较新的 Django 版本中(我使用的是 2.1)已经更新了这个,现在它在 user_login_failed 信号中包含了请求对象:

https://docs.djangoproject.com/en/2.1/ref/contrib/auth/#django.contrib.auth.signals.user_login_failed

【讨论】:

【参考方案3】:

您可以覆盖登录表单并在那里拦截它。 它在那个阶段有请求。

import logging
from django.contrib.admin.forms import AdminAuthenticationForm
from django import forms

log = logging.getLogger(__name__)


class AuthenticationForm(AdminAuthenticationForm):
    def clean(self):
        # to cover more complex cases:
        # http://***.com/questions/4581789/how-do-i-get-user-ip-address-in-django
        ip = request.META.get('REMOTE_ADDR')
        try:
            data = super(AuthenticationForm, self).clean()
        except forms.ValidationError:
            log.info('Login Failed (%s) from (%s)', self.cleaned_data.get('username'), ip)
            raise

        if bool(self.user_cache):
            log.info('Login Success (%s) from (%s)', self.cleaned_data.get('username'), ip)
        else:
            log.info('Login Failed (%s) from (%s)', self.cleaned_data.get('username'), ip)

        return data

要将其安装到站点中,您需要将其附加到 django.contrib.admin.site.login_form

我建议在你的应用程序的 ready() 方法中这样做:

from django.contrib.admin import site as admin_site

class Config(AppConfig):
    ...

    def ready(self):
        # Attach the logging hook to the login form
        from .forms import AuthenticationForm
        admin_site.login_form = AuthenticationForm

【讨论】:

以上是关于Django 记录 user_login_failed 信号的用户 IP的主要内容,如果未能解决你的问题,请参考以下文章

使用 django-simple-history 跟踪具有外键历史记录的 Django 模型历史记录

为啥这个 Django 日志记录不起作用?

Django 详细请求日志记录

在 Django 的管理员上记录活动 - Django

Django 1.3 日志记录:未记录 500 个错误

Django - 编辑现有记录