Obwohl Harolds Antwort in diesem speziellen Fall funktioniert, kann ich mindestens zwei wichtige Probleme damit erkennen:
- Diese Lösung kann nur mit einer Datenbanksitzungs- Engine verwendet werden . In anderen Situationen (Cache, Datei, Cookie) wird das
Session
Modell nicht verwendet.
- Wenn die Anzahl der Sitzungen und Benutzer in der Datenbank zunimmt, wird dies ziemlich ineffizient.
Um diese Probleme zu lösen, schlage ich vor, dass Sie das Problem anders angehen. Die Idee ist, irgendwo das Datum zu speichern, an dem der Benutzer für eine bestimmte Sitzung angemeldet war, und das letzte Mal, als Sie einen Benutzer zum Abmelden aufgefordert haben.
Dann , wenn jemand Zugriff auf Ihrer Website, wenn das Datum angemeldet ist niedriger als das Abmeldedatum, können Sie zwangsAbmelde den Benutzer. Wie Dan sagte, gibt es keinen praktischen Unterschied zwischen dem sofortigen Abmelden eines Benutzers oder seiner nächsten Anfrage an Ihre Site.
Lassen Sie uns nun eine mögliche Implementierung dieser Lösung für django 1.3b1 sehen . In drei Schritten:
1. Speichern Sie in der Sitzung das letzte Anmeldedatum
Glücklicherweise gibt das Django-Authentifizierungssystem ein Signal aus, das aufgerufen wird user_logged_in
. Sie müssen nur diese Signale registrieren und das aktuelle Datum in der Sitzung speichern. Am Ende Ihres models.py
:
from django.contrib.auth.signals import user_logged_in
from datetime import datetime
def update_session_last_login(sender, user=user, request=request, **kwargs):
if request:
request.session['LAST_LOGIN_DATE'] = datetime.now()
user_logged_in.connect(update_session_last_login)
2. Fordern Sie eine Force-Abmeldung für einen Benutzer an
Wir müssen dem User
Modell nur ein Feld und eine Methode hinzufügen . Es gibt mehrere Möglichkeiten, dies zu erreichen ( Benutzerprofile , Modellvererbung usw.), die jeweils Vor- und Nachteile haben.
Der Einfachheit halber werde ich hier die Modellvererbung verwenden. Wenn Sie sich für diese Lösung entscheiden, vergessen Sie nicht , ein benutzerdefiniertes Authentifizierungs-Backend zu schreiben .
from django.contrib.auth.models import User
from django.db import models
from datetime import datetime
class MyUser(User):
force_logout_date = models.DateTimeField(null=True, blank=True)
def force_logout(self):
self.force_logout_date = datetime.now()
self.save()
Wenn Sie dann die Abmeldung für den Benutzer erzwingen möchten johndoe
, müssen Sie nur:
from myapp.models import MyUser
MyUser.objects.get(username='johndoe').force_logout()
3. Implementieren Sie die Zugriffsprüfung
Der beste Weg hier ist, eine Middleware zu verwenden, wie Dan vorgeschlagen hat. Diese Middleware zugreifen request.user
, also setzen Sie sie brauchen , um nach 'django.contrib.auth.middleware.AuthenticationMiddleware'
Ihrer MIDDLEWARE_CLASSES
Einstellung.
from django.contrib.auth import logout
class ForceLogoutMiddleware(object):
def process_request(self, request):
if request.user.is_authenticated() and request.user.force_logout_date and \
request.session['LAST_LOGIN_DATE'] < request.user.force_logout_date:
logout(request)
Das sollte es tun.
Anmerkungen
- Beachten Sie die Auswirkungen auf die Leistung, wenn Sie ein zusätzliches Feld für Ihre Benutzer speichern. Durch die Verwendung der Modellvererbung wird ein zusätzliches Element hinzugefügt
JOIN
. Durch die Verwendung von Benutzerprofilen wird eine zusätzliche Abfrage hinzugefügt. Direktes Ändern User
ist der beste Weg, um die Leistung zu verbessern, aber es ist immer noch ein haariges Thema .
Wenn Sie diese Lösung auf einer vorhandenen Site bereitstellen, haben Sie wahrscheinlich Probleme mit vorhandenen Sitzungen, die nicht über den 'LAST_LOGIN_DATE'
Schlüssel verfügen . Sie können den Middleware-Code ein wenig anpassen, um diesen Fall zu behandeln:
from django.contrib.auth import logout
class ForceLogoutMiddleware(object):
def process_request(self, request):
if request.user.is_authenticated() and request.user.force_logout_date and \
( 'LAST_LOGIN_DATE' not in request.session or \
request.session['LAST_LOGIN_DATE'] < request.user.force_logout_date ):
logout(request)
In Django 1.2.x gibt es kein user_logged_in
Signal. Zurückgreifen auf das Überschreiben der login
Funktion:
from django.contrib.auth import login as dj_login
from datetime import datetime
def login(request, user):
dj_login(request, user)
request.session['LAST_LOGIN_DATE'] = datetime.now()