28

我想一次只允许一个经过身份验证的会话用于我的 Django 应用程序中的个人登录。因此,如果用户使用给定的 IP 地址登录网页,并且这些相同的用户凭据用于从不同的 IP 地址登录,我想做一些事情(注销第一个用户或拒绝访问第二个用户。)

4

4 回答 4

22

不确定这是否仍然需要,但我想我会分享我的解决方案:

1) 安装 django-tracking(感谢 Van Gale 的提示 Google Maps + GeoIP 太棒了!)

2)添加这个中间件:

from django.contrib.sessions.models import Session
from tracking.models import Visitor
from datetime import datetime

class UserRestrictMiddleware(object):
    """
    Prevents more than one user logging in at once from two different IPs
    """
    def process_request(self, request):
        ip_address = request.META.get('REMOTE_ADDR','')
        try:
            last_login = request.user.last_login
        except:
            last_login = 0
        if unicode(last_login)==unicode(datetime.now())[:19]:
            previous_visitors = Visitor.objects.filter(user=request.user).exclude(ip_address=ip_address)
            for visitor in previous_visitors:
                Session.objects.filter(session_key=visitor.session_key).delete()
                visitor.user = None
                visitor.save()

3)确保它在 VisitorTrackingMiddleware 之后,当有人新登录时,您应该会发现以前的登录会自动碰撞:)

于 2009-06-26T13:05:50.250 回答
10

如果您已经按照此处的建议使用 django-tracking,则有一种更简单的方法可以实现:

定义一个信号处理程序:

# myapp/signals.py
def kick_my_other_sessions(sender, request=None, user=None, **kwargs):
    from tracking.models import Visitor
    from django.contrib.sessions.models import Session
    keys = [v.session_key for v in Visitor.objects.filter(user=request.user).exclude(session_key=request.session.session_key)]
    Session.objects.filter(session_key__in=keys).delete()

为 user_logged_in 信号创建一个监听器:

# myapp/__init__.py
from myapp.signals import kick_my_other_sessions
from django.contrib.auth.signals import user_logged_in
user_logged_in.connect(kick_my_other_sessions, sender=User)

这将建立一种“最后登录用户获胜”的系统。如果您想允许同一用户从同一 ip 进行多次登录,您可以.exclude()Visitors查找中添加一个。

于 2012-03-01T16:32:49.180 回答
7

Django 的中间件可能会帮助您实现这一目标。问题是您可能希望允许来自同一 IP 地址的多个匿名会话,甚至是不同用户的经过身份验证的会话,但不允许同一用户的经过身份验证的会话。

你会想要:

  1. 创建一个用户配置文件模型来存储用户上次登录的 IP 地址。请参阅 Django存储有关用户文档的附加信息。

  2. 实施自定义身份验证后端。此后端在触发并成功验证用户身份时(只需调用 super)将清除用户在配置文件模型中的最后登录 IP。

  3. 实现 Django 类的子django.contrib.sessions.SessionMiddleware类。实施process_request。如果request.user对象的配置文件模型没有 IP 地址,则设置它并允许请求。如果它有一个 IP,并且该 IP 与当前请求的 IP ( request.META.REMOTE_ADDR) 不同,则执行您喜欢的任何操作以注销其他用户,或向请求者返回错误。

  4. 更新您的settings.py文件,以便首先处理您的自定义身份验证后端,并首先处理您的自定义会话中间件。这涉及更新settings.AUTHENTICATION_BACKENDSsettings.MIDDLEWARE_CLASSES.

于 2009-05-04T23:52:15.247 回答
6

您需要使用自定义中间件来执行此操作。

在您的中间件process_request()方法中,您将可以访问请求对象,因此您可以执行以下操作:

session_key = request.session.session_key
ip_address = request.META.get('REMOTE_ADDR', '')

现在您知道了 IP 地址,因此请检查您创建的模型(大致)如下所示:

class SessionIPS(models.Model):
    session = models.ForeignKey(Session)
    IP = models.CharField(max_length=20)

因此,当创建或删除会话时,您将相应地修改会话 ip 的表,并且当请求进入时,请确保 IP 地址没有被用于另一个会话。如果是,则从中间件返回一个 Http404(或类似的东西)。

django-tracking是一个可以向您展示更多细节(甚至在其自己的模型中包含 IP 地址)的可插拔应用程序。

于 2009-05-04T23:39:09.973 回答