From 29aa31d8f5dd10ed30e539bebc17735e3b4ae89c Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Thu, 22 Mar 2007 02:20:33 +0000 Subject: [PATCH] Reduced the chances of session object collision. The window of opportunity is now about five Python instructions in get_or_create(). This doesn't guarantee no collisions, but should fix many occurrences. Refs #1180. git-svn-id: http://code.djangoproject.com/svn/django/trunk@4771 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/sessions/middleware.py | 7 ++++++- django/contrib/sessions/models.py | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py index c134a9c9cf..1498f3c8ba 100644 --- a/django/contrib/sessions/middleware.py +++ b/django/contrib/sessions/middleware.py @@ -83,7 +83,12 @@ class SessionMiddleware(object): if accessed: patch_vary_headers(response, ('Cookie',)) if modified or settings.SESSION_SAVE_EVERY_REQUEST: - session_key = request.session.session_key or Session.objects.get_new_session_key() + if request.session.session_key: + session_key = request.session.session_key + else: + obj = Session.objects.get_new_session_object() + session_key = obj.session_key + if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE: max_age = None expires = None diff --git a/django/contrib/sessions/models.py b/django/contrib/sessions/models.py index f684cd381e..77718407e1 100644 --- a/django/contrib/sessions/models.py +++ b/django/contrib/sessions/models.py @@ -1,4 +1,4 @@ -import base64, md5, random, sys +import base64, md5, random, sys, datetime import cPickle as pickle from django.db import models from django.utils.translation import gettext_lazy as _ @@ -23,6 +23,23 @@ class SessionManager(models.Manager): break return session_key + def get_new_session_object(self): + """ + Returns a new session object. + """ + # FIXME: There is a *small* chance of collision here, meaning we will + # return an existing object. That can be fixed when we add a way to + # validate (and guarantee) that non-auto primary keys are unique. For + # now, we save immediately in order to reduce the "window of + # misfortune" as much as possible. + created = False + while not created: + obj, created = self.get_or_create(session_key=self.get_new_session_key(), + expire_date = datetime.datetime.now()) + # Collision in key generation, so re-seed the generator + random.seed() + return obj + def save(self, session_key, session_dict, expire_date): s = self.model(session_key, self.encode(session_dict), expire_date) if session_dict: