2009-05-04 8 views
21

Chcę zezwolić tylko na jedną sesję uwierzytelnioną w tym samym czasie na indywidualne logowanie w mojej aplikacji Django. Więc jeśli użytkownik jest zalogowany na stronie pod danym adresem IP i te same poświadczenia użytkownika są używane do logowania z innego adresu IP, chcę coś zrobić (wylogować pierwszego użytkownika lub odmówić dostępu do drugiego użytkownika.)Jak mogę wykryć wiele loginów w aplikacji internetowej Django z różnych lokalizacji?

Odpowiedz

18

Nie wiem, czy to jest nadal potrzebne, ale myślałem, że dzielę rozwiązanie:

1) Instalacja Django śledzenia (Dziękuje za tą końcówką Van Gale Mapy Google + GeoIP jest niesamowite!)

2) Dodaj middleware:

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) Upewnij się, że idzie po VisitorTrackingMiddleware i należy znaleźć wcześniejsze logowania są automatycznie wpadł gdy ktoś nowy dzienniki w :)

+0

Czy możemy zaufać śledzeniu Django po tylu latach bezczynności? – NikosKeyz

6

Musisz to zrobić za pomocą niestandardowego oprogramowania pośredniego.

W swojej metodzie pośredniej process_request() będziesz mieć dostęp do obiektu żądania, dzięki czemu można zrobić coś jak następuje:

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

Teraz znasz adres IP, więc sprawdź model tworzonych że (w przybliżeniu) będzie wyglądać następująco:

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

Więc gdy sesja jest utworzony lub usunięty będziesz modifiy tabela sesji IP odpowiednio, a kiedy nadejdzie żądanie upewnij się, że adres IP nie jest wykorzystywany do innej sesji. Jeśli tak, to zwróć Http404 (lub coś podobnego) z oprogramowania pośredniego.

Dodatkową aplikacją, która może pokazać znacznie więcej szczegółów (a nawet zawiera adres IP we własnym modelu) jest django-tracking.

6

Prawdopodobnie pomoże to Django middleware. Problem polega na tym, że prawdopodobnie będziesz chciał zezwolić na wiele anonimowych sesji z tego samego adresu IP, nawet uwierzytelnionych sesji dla różnych użytkowników, ale nie uwierzytelnionych sesji dla tego samego użytkownika.

Będziesz chcą:

  1. Tworzenie modelu profilu użytkownika, aby zapisać adres IP logowania użytkownika. Zobacz dokumentację Django: Storing additional information about users.

  2. Wykonaj custom authentication backend. Ten backend, po uruchomieniu i pomyślnym uwierzytelnieniu użytkownika (po prostu zadzwoń do super), wymazał ostatni login użytkownika w modelu profilu.

  3. Implementacja podklasy klasy Django: django.contrib.sessions.SessionMiddleware. Implementacja process_request. Jeśli model profilu obiektu request.user nie ma adresu IP, ustaw go i zezwól na żądanie. Jeśli ma adres IP, a adres IP różni się od adresu IP bieżącego żądania (request.META.REMOTE_ADDR), zrób to, co chcesz, albo wyloguj innego użytkownika, albo zwróć błąd żądającemu.

  4. Zaktualizuj swój plik settings.py, tak aby niestandardowy serwer uwierzytelniania był przetwarzany jako pierwszy, a także aby twoje niestandardowe oprogramowanie pośrednie sesji było przetwarzane jako pierwsze. Wymaga to aktualizacji settings.AUTHENTICATION_BACKENDS i settings.MIDDLEWARE_CLASSES.

9

Jeśli” re już przy użyciu django śledzenia jako sugerowane tu, tam jest dużo łatwiejszy sposób zaimplementować to:

Definiowanie obsługi sygnału:

# 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() 

Utwórz detektor sygnału 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) 

To zapoczątkuje coś w rodzaju „ostatniego użytkownika, aby zalogować wygrywa” systemu. Jeśli chcesz zezwolić na wielokrotne logowanie przez tego samego użytkownika z tego samego adresu IP, możesz dodać do porównania .exclude() do wyszukiwania Visitors.

+0

Przydaje się również ustawienie 'visitor.user = None' dla każdego dopasowanego gościa, w przeciwnym razie kod ten będzie nadal znajdował odwiedzających dla już usuniętych sesji przy każdym logowaniu. (Ma to znaczenie, jeśli zdecydujesz się dodać wiadomość, aby poinformować nowo zalogowanego użytkownika, że ​​właśnie wylogowałeś się z innej sesji). – Duncan

Powiązane problemy