summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2021-01-11 21:27:01 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-01-14 17:50:04 +0100
commit8250145a0cbfd15aa16c2ad4e2235d1afe3a7359 (patch)
tree60b0d8992356c648fc6076f202f3b028b200f261
parent66b4046d68921edc7c83076da4aafd307f7dd19b (diff)
Refs #31274 -- Removed support for the pre-Django 3.1 encoding format of sessions.
Per deprecation timeline.
-rw-r--r--django/contrib/sessions/backends/base.py57
-rw-r--r--docs/releases/4.0.txt2
-rw-r--r--tests/sessions_tests/tests.py26
3 files changed, 15 insertions, 70 deletions
diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py
index 143c08fbef..62ee1f0d89 100644
--- a/django/contrib/sessions/backends/base.py
+++ b/django/contrib/sessions/backends/base.py
@@ -1,16 +1,11 @@
-import base64
import logging
import string
from datetime import datetime, timedelta
from django.conf import settings
-from django.contrib.sessions.exceptions import SuspiciousSession
from django.core import signing
-from django.core.exceptions import SuspiciousOperation
from django.utils import timezone
-from django.utils.crypto import (
- constant_time_compare, get_random_string, salted_hmac,
-)
+from django.utils.crypto import get_random_string
from django.utils.module_loading import import_string
# session_key should not be case sensitive because some backends can store it
@@ -91,16 +86,8 @@ class SessionBase:
def delete_test_cookie(self):
del self[self.TEST_COOKIE_NAME]
- def _hash(self, value):
- # RemovedInDjango40Warning: pre-Django 3.1 format will be invalid.
- key_salt = "django.contrib.sessions" + self.__class__.__name__
- return salted_hmac(key_salt, value).hexdigest()
-
def encode(self, session_dict):
"Return the given session dictionary serialized and encoded as a string."
- # RemovedInDjango40Warning: DEFAULT_HASHING_ALGORITHM will be removed.
- if settings.DEFAULT_HASHING_ALGORITHM == 'sha1':
- return self._legacy_encode(session_dict)
return signing.dumps(
session_dict, salt=self.key_salt, serializer=self.serializer,
compress=True,
@@ -109,44 +96,14 @@ class SessionBase:
def decode(self, session_data):
try:
return signing.loads(session_data, salt=self.key_salt, serializer=self.serializer)
- # RemovedInDjango40Warning: when the deprecation ends, handle here
- # exceptions similar to what _legacy_decode() does now.
except signing.BadSignature:
- try:
- # Return an empty session if data is not in the pre-Django 3.1
- # format.
- return self._legacy_decode(session_data)
- except Exception:
- logger = logging.getLogger('django.security.SuspiciousSession')
- logger.warning('Session data corrupted')
- return {}
+ logger = logging.getLogger('django.security.SuspiciousSession')
+ logger.warning('Session data corrupted')
except Exception:
- return self._legacy_decode(session_data)
-
- def _legacy_encode(self, session_dict):
- # RemovedInDjango40Warning.
- serialized = self.serializer().dumps(session_dict)
- hash = self._hash(serialized)
- return base64.b64encode(hash.encode() + b':' + serialized).decode('ascii')
-
- def _legacy_decode(self, session_data):
- # RemovedInDjango40Warning: pre-Django 3.1 format will be invalid.
- encoded_data = base64.b64decode(session_data.encode('ascii'))
- try:
- # could produce ValueError if there is no ':'
- hash, serialized = encoded_data.split(b':', 1)
- expected_hash = self._hash(serialized)
- if not constant_time_compare(hash.decode(), expected_hash):
- raise SuspiciousSession("Session data corrupted")
- else:
- return self.serializer().loads(serialized)
- except Exception as e:
- # ValueError, SuspiciousOperation, unpickling exceptions. If any of
- # these happen, just return an empty dictionary (an empty session).
- if isinstance(e, SuspiciousOperation):
- logger = logging.getLogger('django.security.%s' % e.__class__.__name__)
- logger.warning(str(e))
- return {}
+ # ValueError, unpickling exceptions. If any of these happen, just
+ # return an empty dictionary (an empty session).
+ pass
+ return {}
def update(self, dict_):
self._session.update(dict_)
diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt
index a2f04227fd..a6f5bdb12e 100644
--- a/docs/releases/4.0.txt
+++ b/docs/releases/4.0.txt
@@ -283,3 +283,5 @@ to remove usage of these features.
* Support for the pre-Django 3.1 password reset tokens in the admin site (that
use the SHA-1 hashing algorithm) is removed.
+
+* Support for the pre-Django 3.1 encoding format of sessions is removed.
diff --git a/tests/sessions_tests/tests.py b/tests/sessions_tests/tests.py
index 73d2a13a9f..c2743ef48b 100644
--- a/tests/sessions_tests/tests.py
+++ b/tests/sessions_tests/tests.py
@@ -31,13 +31,13 @@ from django.core import management
from django.core.cache import caches
from django.core.cache.backends.base import InvalidCacheBackendError
from django.core.exceptions import ImproperlyConfigured
+from django.core.signing import TimestampSigner
from django.http import HttpResponse
from django.test import (
RequestFactory, SimpleTestCase, TestCase, ignore_warnings,
override_settings,
)
from django.utils import timezone
-from django.utils.deprecation import RemovedInDjango40Warning
from .models import SessionStore as CustomDatabaseSession
@@ -315,25 +315,6 @@ class SessionTestsMixin:
encoded = self.session.encode(data)
self.assertEqual(self.session.decode(encoded), data)
- @override_settings(SECRET_KEY='django_tests_secret_key')
- def test_decode_legacy(self):
- # RemovedInDjango40Warning: pre-Django 3.1 sessions will be invalid.
- legacy_encoded = (
- 'OWUzNTNmNWQxNTBjOWExZmM4MmQ3NzNhMDRmMjU4NmYwNDUyNGI2NDp7ImEgdGVzd'
- 'CBrZXkiOiJhIHRlc3QgdmFsdWUifQ=='
- )
- self.assertEqual(
- self.session.decode(legacy_encoded),
- {'a test key': 'a test value'},
- )
-
- @ignore_warnings(category=RemovedInDjango40Warning)
- def test_default_hashing_algorith_legacy_decode(self):
- with self.settings(DEFAULT_HASHING_ALGORITHM='sha1'):
- data = {'a test key': 'a test value'}
- encoded = self.session.encode(data)
- self.assertEqual(self.session._legacy_decode(encoded), data)
-
def test_decode_failure_logged_to_security(self):
tests = [
base64.b64encode(b'flaskdj:alkdjf').decode('ascii'),
@@ -346,6 +327,11 @@ class SessionTestsMixin:
# The failed decode is logged.
self.assertIn('Session data corrupted', cm.output[0])
+ def test_decode_serializer_exception(self):
+ signer = TimestampSigner(salt=self.session.key_salt)
+ encoded = signer.sign(b'invalid data')
+ self.assertEqual(self.session.decode(encoded), {})
+
def test_actual_expiry(self):
# this doesn't work with JSONSerializer (serializing timedelta)
with override_settings(SESSION_SERIALIZER='django.contrib.sessions.serializers.PickleSerializer'):