Code

Ticket #18194: files-sessions-server-expiry-3.patch

File files-sessions-server-expiry-3.patch, 3.5 KB (added by crodjer, 2 years ago)

Patch 3 - Use the signing frework to handle session expiry and integrity

  • django/contrib/sessions/backends/base.py

    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 
    1212from django.utils.crypto import get_random_string 
    1313from django.utils.crypto import salted_hmac 
    1414from django.utils import timezone 
     15from django.core import signing 
    1516 
    1617class CreateError(Exception): 
    1718    """ 
    class SessionBase(object): 
    3132        self._session_key = session_key 
    3233        self.accessed = False 
    3334        self.modified = False 
     35        self.signer = signing.TimestampSigner() 
    3436 
    3537    def __contains__(self, key): 
    3638        return key in self._session 
    class SessionBase(object): 
    7678 
    7779    def encode(self, session_dict): 
    7880        "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) 
    8283 
    8384    def decode(self, session_data): 
    84         encoded_data = base64.decodestring(session_data) 
    8585        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. 
    9396        except Exception: 
    9497            # ValueError, SuspiciousOperation, unpickling exceptions. If any of 
    9598            # these happen, just return an empty dictionary (an empty session). 
  • django/contrib/sessions/tests.py

    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): 
    345345        self.assertRaises(SuspiciousOperation, 
    346346                          self.backend("a/b/c").load) 
    347347 
     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')) 
    348368 
    349369class CacheSessionTests(SessionTestsMixin, unittest.TestCase): 
    350370