Skip to content

Commit 29aa31d

Browse files
committed
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 django#1180. git-svn-id: http://code.djangoproject.com/svn/django/trunk@4771 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 3f3f51d commit 29aa31d

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

django/contrib/sessions/middleware.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,12 @@ def process_response(self, request, response):
8383
if accessed:
8484
patch_vary_headers(response, ('Cookie',))
8585
if modified or settings.SESSION_SAVE_EVERY_REQUEST:
86-
session_key = request.session.session_key or Session.objects.get_new_session_key()
86+
if request.session.session_key:
87+
session_key = request.session.session_key
88+
else:
89+
obj = Session.objects.get_new_session_object()
90+
session_key = obj.session_key
91+
8792
if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
8893
max_age = None
8994
expires = None

django/contrib/sessions/models.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import base64, md5, random, sys
1+
import base64, md5, random, sys, datetime
22
import cPickle as pickle
33
from django.db import models
44
from django.utils.translation import gettext_lazy as _
@@ -23,6 +23,23 @@ def get_new_session_key(self):
2323
break
2424
return session_key
2525

26+
def get_new_session_object(self):
27+
"""
28+
Returns a new session object.
29+
"""
30+
# FIXME: There is a *small* chance of collision here, meaning we will
31+
# return an existing object. That can be fixed when we add a way to
32+
# validate (and guarantee) that non-auto primary keys are unique. For
33+
# now, we save immediately in order to reduce the "window of
34+
# misfortune" as much as possible.
35+
created = False
36+
while not created:
37+
obj, created = self.get_or_create(session_key=self.get_new_session_key(),
38+
expire_date = datetime.datetime.now())
39+
# Collision in key generation, so re-seed the generator
40+
random.seed()
41+
return obj
42+
2643
def save(self, session_key, session_dict, expire_date):
2744
s = self.model(session_key, self.encode(session_dict), expire_date)
2845
if session_dict:

0 commit comments

Comments
 (0)