Fixed #14685 - incompatible code in contrib.sessions.models

Thanks to PaulM for the report.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14562 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2010-11-14 22:23:46 +00:00
parent 74f46c0ae2
commit 0324151bec
2 changed files with 31 additions and 17 deletions

View File

@ -3,18 +3,13 @@ import cPickle as pickle
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.utils.hashcompat import md5_constructor
class SessionManager(models.Manager): class SessionManager(models.Manager):
def encode(self, session_dict): def encode(self, session_dict):
""" """
Returns the given session dictionary pickled and encoded as a string. Returns the given session dictionary pickled and encoded as a string.
""" """
pickled = pickle.dumps(session_dict) return SessionStore().encode(session_dict)
pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest()
return base64.encodestring(pickled + pickled_md5)
def save(self, session_key, session_dict, expire_date): def save(self, session_key, session_dict, expire_date):
s = self.model(session_key, self.encode(session_dict), expire_date) s = self.model(session_key, self.encode(session_dict), expire_date)
@ -54,14 +49,6 @@ class Session(models.Model):
verbose_name_plural = _('sessions') verbose_name_plural = _('sessions')
def get_decoded(self): def get_decoded(self):
encoded_data = base64.decodestring(self.session_data) return SessionStore().decode(self.session_data)
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: from django.contrib.sessions.backends.db import SessionStore
from django.core.exceptions import SuspiciousOperation
raise SuspiciousOperation("User tampered with session cookie.")
try:
return pickle.loads(pickled)
# Unpickling can cause a variety of exceptions. If something happens,
# just return an empty dictionary (an empty session).
except:
return {}

View File

@ -263,6 +263,33 @@ class DatabaseSessionTests(SessionTestsMixin, TestCase):
backend = DatabaseSession backend = DatabaseSession
def test_session_get_decoded(self):
"""
Test we can use Session.get_decoded to retrieve data stored
in normal way
"""
self.session['x'] = 1
self.session.save()
s = Session.objects.get(session_key=self.session.session_key)
self.assertEqual(s.get_decoded(), {'x': 1})
def test_sessionmanager_save(self):
"""
Test SessionManager.save method
"""
# Create a session
self.session['y'] = 1
self.session.save()
s = Session.objects.get(session_key=self.session.session_key)
# Change it
Session.objects.save(s.session_key, {'y':2}, s.expire_date)
# Clear cache, so that it will be retrieved from DB
del self.session._session_cache
self.assertEqual(self.session['y'], 2)
class CacheDBSessionTests(SessionTestsMixin, TestCase): class CacheDBSessionTests(SessionTestsMixin, TestCase):