Commits

Anonymous committed 0ab7259

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.

Comments (0)

Files changed (2)

django/contrib/sessions/middleware.py

             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

django/contrib/sessions/models.py

-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 _
                 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:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.