Как я могу обнаружить несколько входов в веб-приложение Django из разных мест?

Я хочу разрешить только одну аутентифицированную сессию за раз для отдельного входа в мое приложение Django. Поэтому, если пользователь вошел на веб-страницу с заданным IP-адресом и эти же учетные данные используются для входа с другого IP-адреса, я хочу что-то сделать (либо выйти из системы первого пользователя, либо запретить доступ второму пользователю).

4 ответа

Решение

Не уверен, что это все еще нужно, но думал, что поделюсь своим решением:

1) Установите django-tracking (спасибо за этот совет, Ван Гейл, 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, и вы должны обнаружить, что предыдущие входы в систему автоматически поднимаются, когда кто-то новый входит в систему:)

Если вы уже используете 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 уважать.

Промежуточное программное обеспечение Django, вероятно, поможет вам достичь этого. Проблема в том, что вы, вероятно, захотите разрешить несколько анонимных сеансов с одного IP-адреса, даже сеансы с проверкой подлинности для разных пользователей, но не сеансы с проверкой подлинности для одного и того же пользователя.

Вы хотите:

  1. Создайте модель профиля пользователя для хранения IP-адреса последнего логина пользователя. Смотрите Django's Storing дополнительную информацию о пользовательской документации.

  2. Реализуйте пользовательский бэкэнд аутентификации Этот бэкэнд, при запуске и успешной аутентификации пользователя (просто вызовите super) уничтожил бы последний IP-адрес пользователя в модели профиля.

  3. Реализовать подкласс Django's django.contrib.sessions.SessionMiddleware учебный класс. Воплощать в жизнь process_request, Если request.user Модель профиля объекта не имеет IP-адреса, установите его и разрешите запрос. Если у него есть IP, и этот IP отличается от IP текущего запроса (request.META.REMOTE_ADDR), затем сделайте все, что захотите, чтобы выйти из системы другого пользователя или вернуть ошибку запрашивающей стороне.

  4. Обновите свой settings.py файл так, чтобы ваш пользовательский аутентификационный бэкэнд обрабатывался первым, и чтобы ваше пользовательское промежуточное программное обеспечение сеанса также обрабатывалось первым. Это включает обновление settings.AUTHENTICATION_BACKENDS а также settings.MIDDLEWARE_CLASSES,

Вам нужно будет сделать это с помощью специального промежуточного программного обеспечения.

В вашем промежуточном программном обеспечении 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 (или что-то подобное) из промежуточного программного обеспечения.

Подключаемое приложение, которое может показать вам гораздо больше деталей (и даже включает IP-адрес в своей собственной модели), является django-tracking.

Другие вопросы по тегам