Я хочу разрешить только один аутентифицированный сеанс за один раз для отдельного входа в приложение Django. Поэтому, если пользователь зарегистрирован на веб-странице по заданному IP-адресу, и те же учетные данные пользователя используются для входа с другого IP-адреса, я хочу что-то сделать (либо выйти из первого пользователя, либо отказаться от доступа ко второму пользователю.)
Как я могу обнаружить несколько логинов в веб-приложении Django из разных мест?
Ответ 1
Не уверен, что это все еще необходимо, но я решил поделиться своим решением:
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, и вы должны найти, что предыдущие логины автоматически ударяются, когда у кого-то новые журналы:)
Ответ 2
Если вы уже используете 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
.
Ответ 3
Вам нужно будет сделать это с помощью специального промежуточного программного обеспечения.
В методе промежуточного программного обеспечения 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-адрес не используется для другого сеанса. Если if is, то верните Http404 (или что-то вроде этого) из промежуточного ПО.
Подключаемое приложение, которое может показать вам гораздо больше деталей (и даже включает IP-адрес в его собственной модели), django-tracking.
Ответ 4
Django middleware, вероятно, поможет вам в этом. Проблема в том, что вы, вероятно, захотите разрешить нескольким анонимным сеансам с одного и того же IP-адреса, даже проверенные сеансы для разных пользователей, но не аутентифицированные сеансы для одного и того же пользователя.
Вы хотите:
-
Создайте модель профиля пользователя, чтобы сохранить IP-адрес последнего входа пользователя в систему. См. Django Сохранение дополнительной информации о документации пользователей.
-
Внедрите настраиваемый сервер аутентификации. Этот бэкэнд при запуске и успешной аутентификации пользователя (просто вызов супер) уничтожит последний IP-адрес пользователя в модели профиля.
-
Внедрить подкласс класса Django
django.contrib.sessions.SessionMiddleware
. Внеситеprocess_request
. Если модель профиля объектаrequest.user
не имеет IP-адреса, установите его и разрешите запрос. Если у него есть IP, а IP отличается от текущего IP-адреса запроса (request.META.REMOTE_ADDR
), то делайте то, что вам нравится, либо выходите из системы другим пользователем, либо возвращаете ошибку запрашивающему. -
Обновите файл
settings.py
, чтобы сначала обработать ваш собственный сервер архивации и так, чтобы ваше промежуточное программное обеспечение сеанса также обрабатывалось первым. Это включает в себя обновлениеsettings.AUTHENTICATION_BACKENDS
иsettings.MIDDLEWARE_CLASSES
.