Meilo
Meilo

Reputation: 3418

Django request's session consistency across different browsers

I have the session engine settings as follows:

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
SESSION_SAVE_EVERY_REQUEST = True
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
        'TIMEOUT': 60*60,
    }
}

I go to 127.0.0.1:8000 with Browser 1 and can successfully log in.

Then I go to 127.0.0.1:8000 with Browser 2 and can also successfully log in.

Now I go to 127.0.0.1:8000 with Browser 1 and get the following error message:

SuspiciousOperation at /

The request's session was deleted before the request completed.
The user may have logged out in a concurrent request, for example.

How can this error be avoided? The user should be able to log in with as many browsers as he likes. I don't mind if he gets logged out from the non-active browsers, but an error is not acceptable.

Upvotes: 2

Views: 294

Answers (1)

Meilo
Meilo

Reputation: 3418

The problem was a middleware in place that ensured that only one session can be active at the same time. It was writen for session cookies only and after rewriting it more generally the problem has disappeared:

from importlib import import_module
class OnlyOneSessionMiddleware:
    """
    Middleware to ensure that a logged-in user only has one session active.
    Will kick out any previous session. 
    """
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        if request.user.is_authenticated:
            cur_session_key = request.user.profile.session_key
            if cur_session_key and cur_session_key != request.session.session_key:
                # Default handling: Kick out the old session...
                SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
                s = SessionStore(session_key=cur_session_key)
                s.delete()
                messages.add_message(request, messages.INFO, 'You have now been automatically logged out from your other Cableizer session.')
            if not cur_session_key or cur_session_key != request.session.session_key:
                request.user.profile.session_key = request.session.session_key
                request.user.profile.save()
        return response

Upvotes: 1

Related Questions