How to determine when a user has an idle timeout in Django?

I would like to conduct an audit when a user experiences an idle timeout in my Django application. In other words, if the user's session cookie expiration date exceeds the SESSION_COOKIE_AGE found in settings.py, the user is redirected to the login page. When this happens, an audit should also be conducted. By "audit" I mean that the record should be written to my person.audit table.

I have currently set up some middleware to capture these events. Unfortunately, Django creates a new cookie when the user is redirected to the login page, so I can’t determine if the user was sent to the login page through an idle timeout or some other event.

From what I can say, I will need to work with the django_session table. However, entries in this table cannot be associated with this user, since the sessionid value in the cookie is reset when a redirect occurs.

I guess I'm not the first to face this dilemma. Does anyone know how to solve a problem?

+5
source share
3 answers

Update:

, . , , prev_session_data, , .

-, :

  • URL- , - (request.user - AnonymousUser).
  • , , .
  • (SessionStore._session); accessed modified .
  • SessionMiddleware , Session django_session ( , , django.contrib.sessions.backends.db). cookie settings.SESSION_COOKIE_NAME.
  • , . , login django.contrib.auth. login , ; , , SessionStore.cycle_key, , . SessionStore.flush, . ( ) SessionStore.create .
  • , . , . settings.SESSION_COOKIE_NAME.

, , - create ( 5.), . , , , cookie , .

, , , , , , , - . , "" cookie, , cookie. :

  • cookie , cookie , , ,
  • cookie , cookie , , , , .
  • cookie ,

:

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',
    ...
)

, , cookie , . , django signed-cookies ( , , , ?)

OLD:

, , . () :

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

"customdb.py" django. settings.py "SESSION_ENGINE" , :

SESSION_ENGINE = 'yourproject.customdb'

models.py session_created, :

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)

, models.py INSTALLED_APPS.

+9

SESSION_COOKIE_AGE = 1500 # 25

, .

+1

Django, cookie, ( cookie ).

Then, on the login page, you can check if your user has your cookie, but there is no session, then you know that the user's session may have expired. Since you have the last access time to a page on your site, you can also calculate based on the duration of the session if it has expired.

0
source

All Articles