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:
parent
9b66eae75f
commit
9e423b51e3
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue