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

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

Ответы [ 4 ]

19 голосов
/ 26 июня 2009

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

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, и вы должны обнаружить, что предыдущие входы в систему автоматически поднимаются, когда кто-то входит в систему:)

10 голосов
/ 01 марта 2012

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

7 голосов
/ 05 мая 2009

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

Вы хотите:

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

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

  3. Реализация подкласса класса 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.

6 голосов
/ 05 мая 2009

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

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

...