summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2007-03-22 02:20:33 +0000
committerMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2007-03-22 02:20:33 +0000
commit29aa31d8f5dd10ed30e539bebc17735e3b4ae89c (patch)
tree37928365340c9285050a3082fb30bc8d27754fb2
parent3f3f51d942cc8f3b4fd7c7aab8bf4cbc9747b713 (diff)
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
-rw-r--r--django/contrib/sessions/middleware.py7
-rw-r--r--django/contrib/sessions/models.py19
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: