diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py
index 5a637e2..20d1279 100644
a
|
b
|
from django.utils.crypto import constant_time_compare
|
12 | 12 | from django.utils.crypto import get_random_string |
13 | 13 | from django.utils.crypto import salted_hmac |
14 | 14 | from django.utils import timezone |
| 15 | from django.core import signing |
15 | 16 | |
16 | 17 | class CreateError(Exception): |
17 | 18 | """ |
… |
… |
class SessionBase(object):
|
31 | 32 | self._session_key = session_key |
32 | 33 | self.accessed = False |
33 | 34 | self.modified = False |
| 35 | self.signer = signing.TimestampSigner() |
34 | 36 | |
35 | 37 | def __contains__(self, key): |
36 | 38 | return key in self._session |
… |
… |
class SessionBase(object):
|
76 | 78 | |
77 | 79 | def encode(self, session_dict): |
78 | 80 | "Returns the given session dictionary pickled and encoded as a string." |
79 | | pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL) |
80 | | hash = self._hash(pickled) |
81 | | return base64.encodestring(hash + ":" + pickled) |
| 81 | serialized = pickle.dumps(session_dict) |
| 82 | return self.signer.sign(serialized) |
82 | 83 | |
83 | 84 | def decode(self, session_data): |
84 | | encoded_data = base64.decodestring(session_data) |
85 | 85 | try: |
86 | | # could produce ValueError if there is no ':' |
87 | | hash, pickled = encoded_data.split(':', 1) |
88 | | expected_hash = self._hash(pickled) |
89 | | if not constant_time_compare(hash, expected_hash): |
90 | | raise SuspiciousOperation("Session data corrupted") |
91 | | else: |
92 | | return pickle.loads(pickled) |
| 86 | serialized = str(self.signer.unsign(session_data, |
| 87 | settings.SESSION_COOKIE_AGE)) |
| 88 | return pickle.loads(serialized) |
| 89 | |
| 90 | except signing.BadSignature: |
| 91 | self.create() |
| 92 | |
| 93 | # Signing framework handles any possiblity of ValueError and |
| 94 | # SuspiciousOperation. So, this exception block will handle unpickling |
| 95 | # exceptions only. |
93 | 96 | except Exception: |
94 | 97 | # ValueError, SuspiciousOperation, unpickling exceptions. If any of |
95 | 98 | # these happen, just return an empty dictionary (an empty session). |
diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py
index 92ea6bb..c23a137 100644
a
|
b
|
class FileSessionTests(SessionTestsMixin, unittest.TestCase):
|
345 | 345 | self.assertRaises(SuspiciousOperation, |
346 | 346 | self.backend("a/b/c").load) |
347 | 347 | |
| 348 | # This test fails with cookie (which is fine I suppose) and cache backends, |
| 349 | # thats why added it to file tests only. |
| 350 | @override_settings(SESSION_COOKIE_AGE=0) |
| 351 | def test_onload_expiry_check(self): |
| 352 | """ |
| 353 | Test to ensure that expiry of session is checked on-load |
| 354 | """ |
| 355 | |
| 356 | self.session['test-data'] = True |
| 357 | old_key = self.session.session_key |
| 358 | self.session.save() |
| 359 | self.assertTrue(self.session.get('test-data')) |
| 360 | self.session.load() |
| 361 | new_key = self.session.session_key |
| 362 | |
| 363 | # Make sure a new key was generated after the invalidation of the old |
| 364 | # one. |
| 365 | self.assertNotEqual(old_key, new_key) |
| 366 | # The key test-data should not be present in the session. |
| 367 | self.assertFalse(self.session.get('test-data')) |
348 | 368 | |
349 | 369 | class CacheSessionTests(SessionTestsMixin, unittest.TestCase): |
350 | 370 | |