From c8c159cbbad71deb4d13d6b4e10d4f38817ebdc4 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Thu, 21 Aug 2008 13:54:53 +0000 Subject: [PATCH] When logging in, change the session key whilst preserving any existing sesssion. This means the user will see their session preserved across a login boundary, but somebody snooping the anonymous session key won't be able to view the authenticated session data. This is the final piece of the session key handling changes. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8459 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/auth/__init__.py | 13 +++++++---- django/contrib/sessions/backends/base.py | 10 ++++++++ django/contrib/sessions/tests.py | 29 ++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index e73e34b816..87c2bc1b50 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -53,10 +53,15 @@ def login(request, user): # TODO: It would be nice to support different login methods, like signed cookies. user.last_login = datetime.datetime.now() user.save() - if request.session.get('SESSION_KEY', user.id) != user.id: - # To avoid reusing another user's session, create a new, empty session - # if the existing session corresponds to a different authenticated user. - request.session.flush() + + if SESSION_KEY in request.session: + if request.session[SESSION_KEY] != user.id: + # To avoid reusing another user's session, create a new, empty + # session if the existing session corresponds to a different + # authenticated user. + request.session.flush() + else: + request.session.cycle_key() request.session[SESSION_KEY] = user.id request.session[BACKEND_SESSION_KEY] = user.backend if hasattr(request, 'user'): diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py index b553fa4d58..b4cdeadd81 100644 --- a/django/contrib/sessions/backends/base.py +++ b/django/contrib/sessions/backends/base.py @@ -239,6 +239,16 @@ class SessionBase(object): self.delete() self.create() + def cycle_key(self): + """ + Creates a new session key, whilst retaining the current session data. + """ + data = self._session_cache + key = self.session_key + self.create() + self._session_cache = data + self.delete(key) + # Methods that child classes must implement. def exists(self, session_key): diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py index ffa32d6ae1..5efc17df00 100644 --- a/django/contrib/sessions/tests.py +++ b/django/contrib/sessions/tests.py @@ -37,6 +37,15 @@ False False >>> db_session.modified, db_session.accessed (True, True) +>>> db_session['a'], db_session['b'] = 'c', 'd' +>>> db_session.save() +>>> prev_key = db_session.session_key +>>> prev_data = db_session.items() +>>> db_session.cycle_key() +>>> db_session.session_key == prev_key +False +>>> db_session.items() == prev_data +True # Submitting an invalid session key (either by guessing, or if the db has # removed the key) results in a new key being generated. @@ -75,6 +84,16 @@ False False >>> file_session.modified, file_session.accessed (True, True) +>>> file_session['a'], file_session['b'] = 'c', 'd' +>>> file_session.save() +>>> prev_key = file_session.session_key +>>> prev_data = file_session.items() +>>> file_session.cycle_key() +>>> file_session.session_key == prev_key +False +>>> file_session.items() == prev_data +True + >>> Session.objects.filter(pk=file_session.session_key).delete() >>> file_session = FileSession(file_session.session_key) >>> file_session.save() @@ -112,6 +131,16 @@ False False >>> cache_session.modified, cache_session.accessed (True, True) +>>> cache_session['a'], cache_session['b'] = 'c', 'd' +>>> cache_session.save() +>>> prev_key = cache_session.session_key +>>> prev_data = cache_session.items() +>>> cache_session.cycle_key() +>>> cache_session.session_key == prev_key +False +>>> cache_session.items() == prev_data +True + >>> Session.objects.filter(pk=cache_session.session_key).delete() >>> cache_session = CacheSession(cache_session.session_key) >>> cache_session.save()