Frage

Ich mag prüfen, wenn ein Benutzer eine Leerlaufzeit in meiner Django-Anwendung erfahren hat. Mit anderen Worten, wenn das Ablaufdatum des Benutzers Session-Cookie der SESSION_COOKIE_AGE in settings.py gefunden überschreitet, wird der Benutzer auf die Login-Seite umgeleitet. Wenn das geschieht, sollte eine Prüfung ebenfalls auftreten. Unter „Prüfung“, dann meine ich eine Aufzeichnung sollte meine person.audit Tabelle geschrieben werden.

Zur Zeit habe ich einige Middleware konfiguriert diese Ereignisse zu erfassen. Leider erzeugt Django ein neues Cookie, wenn der Benutzer auf die Anmeldeseite umgeleitet wird, so kann ich nicht feststellen, ob der Benutzer auf die Login-Seite über eine Leerlaufzeitüberschreitung oder ein anderes Ereignis gemacht.

Von dem, was ich sagen kann, brauchte ich, um mit der „django_session“ Tabelle zu arbeiten. Allerdings können die Datensätze in dieser Tabelle nicht mit diesem Benutzer, weil der Sitzungs-Wert im Cookie zugeordnet werden zurückgesetzt, wenn die Umleitung erfolgt.

Ich vermute, ich bin nicht die erste, dieses Dilemma zu begegnen. Hat jemand Einblick in hat, wie das Problem zu lösen?

War es hilfreich?

Lösung

Update:

Nach einem wenig getestet, merke ich, dass der Code unten Ihre Frage nicht beantworten. Obwohl es funktioniert, und das Signal-Handler aufgerufen wird, prev_session_data wenn es vorhanden ist, werden alle nützlichen Informationen nicht enthalten.

Als erstes wird ein innen Blick auf die Sitzungen Rahmen:

  1. Wenn ein neuer Besucher eine Anwendung URL anfordert, eine neue Sitzung für sie erzeugt wird - an diesem Punkt, sind sie immer noch anonym (request.user ist eine Instanz AnonymousUser)
  2. .
  3. Wenn sie einen Blick anfordern, die eine Authentifizierung erforderlich ist, sie auf die Login-Ansicht umgeleitet ist.
  4. Wenn die Anmelde Ansicht angefordert wird, setzt sie einen Testwert in der Sitzung des Benutzers (SessionStore._session); dies setzt automatisch die accessed und modified Flaggen auf der aktuellen Sitzung.
  5. Während der Antwortphase der obigen Anforderung speichert der SessionMiddleware die aktuelle Sitzung, effektiv eine neue Session Instanz in der django_session Tabelle erstellen (wenn Sie die Standard-Datenbank-backed-Sessions verwenden, von django.contrib.sessions.backends.db zur Verfügung gestellt). Die ID der neuen Sitzung im settings.SESSION_COOKIE_NAME Cookie gespeichert.
  6. Wenn der Benutzer in seinem Benutzernamen und Passwort ein und das Formular abschickt, werden sie authentifiziert. Wenn die Authentifizierung erfolgreich ist, wird das Verfahren von login django.contrib.auth genannt. login prüft, ob die aktuelle Sitzung eine Benutzer-ID enthält; wenn es der Fall ist, und die Identifikation ist die gleiche wie die ID des angemeldeten Benutzers wird SessionStore.cycle_key einen neuen Sitzungsschlüssel erstellen genannt, während die Sitzungsdaten beibehalten werden. Andernfalls SessionStore.flush, genannt alle Daten zu entfernen und eine neue Sitzung zu erzeugen. Beide Methoden sollten die vorherige Sitzung (für den anonymen Benutzer) löschen und rufen SessionStore.create eine neue Sitzung zu erstellen.
  7. An diesem Punkt wird der Benutzer authentifiziert, und sie haben eine neue Sitzung. Ihre ID wird in der Sitzung gespeichert, zusammen mit dem Backend verwendet, um sie zu authentifizieren. Die Session-Middleware speichert diese Daten in die Datenbank und speichert die neue Session-ID in settings.SESSION_COOKIE_NAME.

So können Sie das große Problem mit der bisherigen Lösung zu sehen, ist durch die Zeit create (Schritt 5) aufgerufen wird, ID die vorherige Sitzung ist längst vorbei. Wie andere haben darauf hingewiesen, geschieht dies, weil, wenn die Session-Cookie abläuft, es lautlos durch den Browser gelöscht.

Aufbauend auf Alex Gaynor Vorschlag , ich glaube, ich habe mit einem anderen Ansatz kommen, das zu tun scheint, was Sie fragen, wenn es um die Kanten noch ein wenig rau ist. Grundsätzlich verwende ich eine zweite langlebiges „audit“ Cookie, die Session-ID zu spiegeln, und einige Middleware für die Anwesenheit dieses Cookie zu überprüfen. Für jede Anfrage:

  • , wenn weder die Prüfung Cookie noch der Session-Cookie vorhanden ist, ist dies wahrscheinlich ein neuer Benutzer
  • , wenn die Prüfung Cookie vorhanden ist, aber die Session-Cookie nicht der Fall, ist dies wahrscheinlich ein Benutzer, dessen Sitzung abgelaufen nur
  • , wenn beide Cookies vorhanden sind, und den gleichen Wert haben, ist dies eine aktive Sitzung

Hier ist der Code so weit:

sessionaudit.middleware.py :

from django.conf import settings
from django.db.models import signals
from django.utils.http import cookie_date
import time

session_expired = signals.Signal(providing_args=['previous_session_key'])

AUDIT_COOKIE_NAME = 'sessionaudit'

class SessionAuditMiddleware(object):
    def process_request(self, request):
        # The 'print' statements are helpful if you're using the development server
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
        audit_cookie = request.COOKIES.get(AUDIT_COOKIE_NAME, None)
        if audit_cookie is None and session_key is None:
            print "** Got new user **"
        elif audit_cookie and session_key is None:
            print "** User session expired, Session ID: %s **" % audit_cookie
            session_expired.send(self.__class__, previous_session_key=audit_cookie)
        elif audit_cookie == session_key:
            print "** User session active, Session ID: %s **" % audit_cookie

    def process_response(self, request, response):
        if request.session.session_key:
            audit_cookie = request.COOKIES.get(AUDIT_COOKIE_NAME, None)
            if audit_cookie != request.session.session_key:
                # New Session ID - update audit cookie:
                max_age = 60 * 60 * 24 * 365  # 1 year
                expires_time = time.time() + max_age
                expires = cookie_date(expires_time)
                response.set_cookie(
                    AUDIT_COOKIE_NAME,
                    request.session.session_key,
                    max_age=max_age,
                    expires=expires,
                    domain=settings.SESSION_COOKIE_DOMAIN,
                    path=settings.SESSION_COOKIE_PATH,
                    secure=settings.SESSION_COOKIE_SECURE or None
                )
        return response

audit.models.py :

from django.contrib.sessions.models import Session
from sessionaudit.middleware import session_expired

def audit_session_expire(sender, **kwargs):
    try:
        prev_session = Session.objects.get(session_key=kwargs['previous_session_key'])
        prev_session_data = prev_session.get_decoded()
        user_id = prev_session_data.get('_auth_user_id')
    except Session.DoesNotExist:
        pass

session_expired.connect(audit_session_expire)

settings.py :

MIDDLEWARE_CLASSES = (
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'sessionaudit.middleware.SessionAuditMiddleware',
    ...
)

INSTALLED_APPS = (
    ...
    'django.contrib.sessions',
    'audit',
    ...
)

Wenn Sie diese verwenden, sollten Sie eine benutzerdefinierte Abmelde Ansicht implementieren, dass explizit löscht das Audit Cookie, wenn sich der Benutzer abmeldet. Auch ich würde vorschlagen, dass die django unterzeichnet-Cookies Middleware (aber Sie sind wahrscheinlich schon tun, dass, nicht wahr?)

ALT:

Ich denke, Sie sollten diese in der Lage sein zu tun, einen benutzerdefinierten Session-Backend verwenden. Hier einige (nicht getestet) Beispielcode:

from django.contrib.sessions.backends.db import SessionStore as DBStore
from django.db.models import signals

session_created = signals.Signal(providing_args=['previous_session_key', 'new_session_key'])

class SessionStore(DBStore):
    """
    Override the default database session store.

    The `create` method is called by the framework to:
    * Create a new session, if we have a new user
    * Generate a new session, if the current user's session has expired

    What we want to do is override this method, so we can send a signal
    whenever it is called.
    """

    def create(self):
        # Save the current session ID:
        prev_session_id = self.session_key
        # Call the superclass 'create' to create a new session:
        super(SessionStore, self).create()
        # We should have a new session - raise 'session_created' signal:
        session_created.send(self.__class__, previous_session_key=prev_session_id, new_session_key=self.session_key)

Speichern Sie den Code über eins ‚customdb.py‘ und fügen Sie das zu Ihrem django Projekt. In Ihrem settings.py setzen oder ‚SESSION_ENGINE‘ mit dem Pfad zu der obigen Datei ersetzen, z.

SESSION_ENGINE = 'yourproject.customdb'

Dann in Ihrer Middleware oder models.py bietet einen Handler für das 'session_created' Signal, etwa so:

from django.contrib.sessions.models import Session
from yourproject.customdb import session_created

def audit_session_expire(sender, **kwargs):
    # remember that 'previous_session_key' can be None if we have a new user
    try:
        prev_session = Session.objects.get(kwargs['previous_session_key'])
        prev_session_data = prev_session.get_decoded()
        user_id = prev_session_data['_auth_user_id']
        # do something with the user_id
    except Session.DoesNotExist:
        # new user; do something else...

session_created.connect(audit_session_expire)

Vergessen Sie nicht, die App schließen die models.py in INSTALLED_APPS enthält.

Andere Tipps

SESSION_COOKIE_AGE = 1500 # 25 Minuten

Setzen Sie, dass in Ihren Einstellungen und das sollte sich darum kümmern und die Sitzung abläuft.

Ich weiß nicht, über Django, aber können Sie einfach ein nicht-permanentes Cookie erstellen, die die letzte Zugriffszeit auf eine Seite auf Ihrer Website speichert (Sie das Cookie aktualisieren auf jeder Seite zu laden)

Dann auf Ihrer Anmeldeseite können Sie überprüfen, ob Ihre Benutzer Ihre Cookie haben, aber keine Sitzung, dann wissen Sie, dass die Sitzung des Benutzers wahrscheinlich aus abgelaufen ist. Da Sie die Zeit des letzten Zugriffs auf einer Seite auf Ihrer Website haben, können Sie auch berechnen, basierend auf der Dauer der Sitzung, wenn es abgelaufen ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top