Fixed #8314 -- Fixed an infinite loop caused when submitting a session key (via

a cookie) with no corresponding entry in the database.

This only affected the database backend, but I've applied the same fix to all
three backends for robustness.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@8351 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-08-14 19:43:08 +00:00
parent 9b66eae75f
commit 9e423b51e3
5 changed files with 23 additions and 6 deletions

View File

@ -153,13 +153,16 @@ class SessionBase(object):
session_key = property(_get_session_key, _set_session_key) session_key = property(_get_session_key, _set_session_key)
def _get_session(self): def _get_session(self, no_load=False):
# Lazily loads session from storage. """
Lazily loads session from storage (unless "no_load" is True, when only
an empty dict is stored) and stores it in the current instance.
"""
self.accessed = True self.accessed = True
try: try:
return self._session_cache return self._session_cache
except AttributeError: except AttributeError:
if self._session_key is None: if self._session_key is None or no_load:
self._session_cache = {} self._session_cache = {}
else: else:
self._session_cache = self.load() self._session_cache = self.load()

View File

@ -30,7 +30,8 @@ class SessionStore(SessionBase):
func = self._cache.add func = self._cache.add
else: else:
func = self._cache.set func = self._cache.set
result = func(self.session_key, self._session, self.get_expiry_age()) result = func(self.session_key, self._get_session(no_load=must_create),
self.get_expiry_age())
if must_create and not result: if must_create and not result:
raise CreateError raise CreateError

View File

@ -49,7 +49,7 @@ class SessionStore(SessionBase):
""" """
obj = Session( obj = Session(
session_key = self.session_key, session_key = self.session_key,
session_data = self.encode(self._session), session_data = self.encode(self._get_session(no_load=must_create)),
expire_date = self.get_expiry_date() expire_date = self.get_expiry_date()
) )
sid = transaction.savepoint() sid = transaction.savepoint()

View File

@ -73,7 +73,7 @@ class SessionStore(SessionBase):
flags |= os.O_EXCL flags |= os.O_EXCL
# Because this may trigger a load from storage, we must do it before # Because this may trigger a load from storage, we must do it before
# truncating the file to save. # truncating the file to save.
session_data = self._session session_data = self._get_session(no_load=must_create)
try: try:
fd = os.open(self._key_to_file(self.session_key), flags) fd = os.open(self._key_to_file(self.session_key), flags)
try: try:

View File

@ -5,6 +5,7 @@ r"""
>>> from django.contrib.sessions.backends.cache import SessionStore as CacheSession >>> from django.contrib.sessions.backends.cache import SessionStore as CacheSession
>>> from django.contrib.sessions.backends.file import SessionStore as FileSession >>> from django.contrib.sessions.backends.file import SessionStore as FileSession
>>> from django.contrib.sessions.backends.base import SessionBase >>> from django.contrib.sessions.backends.base import SessionBase
>>> from django.contrib.sessions.models import Session
>>> db_session = DatabaseSession() >>> db_session = DatabaseSession()
>>> db_session.modified >>> db_session.modified
@ -36,6 +37,12 @@ False
>>> db_session.modified, db_session.accessed >>> db_session.modified, db_session.accessed
(True, True) (True, True)
# Submitting an invalid session key (either by guessing, or if the db has
# removed the key) results in a new key being generated.
>>> Session.objects.filter(pk=db_session.session_key).delete()
>>> db_session = DatabaseSession(db_session.session_key)
>>> db_session.save()
>>> file_session = FileSession() >>> file_session = FileSession()
>>> file_session.modified >>> file_session.modified
False False
@ -65,6 +72,9 @@ False
False False
>>> file_session.modified, file_session.accessed >>> file_session.modified, file_session.accessed
(True, True) (True, True)
>>> Session.objects.filter(pk=file_session.session_key).delete()
>>> file_session = FileSession(file_session.session_key)
>>> file_session.save()
# Make sure the file backend checks for a good storage dir # Make sure the file backend checks for a good storage dir
>>> settings.SESSION_FILE_PATH = "/if/this/directory/exists/you/have/a/weird/computer" >>> settings.SESSION_FILE_PATH = "/if/this/directory/exists/you/have/a/weird/computer"
@ -99,6 +109,9 @@ False
False False
>>> cache_session.modified, cache_session.accessed >>> cache_session.modified, cache_session.accessed
(True, True) (True, True)
>>> Session.objects.filter(pk=cache_session.session_key).delete()
>>> cache_session = CacheSession(cache_session.session_key)
>>> cache_session.save()
>>> s = SessionBase() >>> s = SessionBase()
>>> s._session['some key'] = 'exists' # Pre-populate the session with some data >>> s._session['some key'] = 'exists' # Pre-populate the session with some data