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: