Как я могу обнаружить несколько входов в веб-приложение 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-адреса, даже сеансы с проверкой подлинности для разных пользователей, но не сеансы с проверкой подлинности для одного и того же пользователя.
Вы хотите:
Создайте модель профиля пользователя для хранения IP-адреса последнего логина пользователя. Смотрите Django's Storing дополнительную информацию о пользовательской документации.
Реализуйте пользовательский бэкэнд аутентификации Этот бэкэнд, при запуске и успешной аутентификации пользователя (просто вызовите super) уничтожил бы последний IP-адрес пользователя в модели профиля.
Реализовать подкласс Django's
django.contrib.sessions.SessionMiddleware
учебный класс. Воплощать в жизньprocess_request
, Еслиrequest.user
Модель профиля объекта не имеет IP-адреса, установите его и разрешите запрос. Если у него есть IP, и этот IP отличается от IP текущего запроса (request.META.REMOTE_ADDR
), затем сделайте все, что захотите, чтобы выйти из системы другого пользователя или вернуть ошибку запрашивающей стороне.Обновите свой
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.