From 1e97de9105515a5e5295e92b64af3168eb45e775 Mon Sep 17 00:00:00 2001 From: Feanil Patel Date: Thu, 17 Oct 2019 16:12:44 -0400 Subject: [PATCH 1/2] Use the default json session serializer. This will force a logout as sessions fail to load but this should be a more performant and secure serializer moving forward. The reason we overwrote it in our config is that it previously used to be the default and we didn't want things to breake and force logouts when we changed it. We're no more okay with people getting logged out. --- cms/envs/common.py | 1 - lms/envs/common.py | 1 - 2 files changed, 2 deletions(-) diff --git a/cms/envs/common.py b/cms/envs/common.py index 96594e01c9..bf60eee34b 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -829,7 +829,6 @@ COURSES_WITH_UNSAFE_CODE = [] DEBUG = False SESSION_COOKIE_SECURE = False SESSION_SAVE_EVERY_REQUEST = False -SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' SESSION_COOKIE_DOMAIN = "" SESSION_COOKIE_NAME = 'sessionid' diff --git a/lms/envs/common.py b/lms/envs/common.py index a2a9a8249e..ef38521367 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1101,7 +1101,6 @@ DEBUG = False USE_TZ = True SESSION_COOKIE_SECURE = False SESSION_SAVE_EVERY_REQUEST = False -SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' SESSION_COOKIE_DOMAIN = "" SESSION_COOKIE_NAME = 'sessionid' From bfc02dc3abad8da6085098daaeb98a4b0de868bd Mon Sep 17 00:00:00 2001 From: Feanil Patel Date: Fri, 18 Oct 2019 10:39:01 -0400 Subject: [PATCH 2/2] Create custom pickle serializer. We need to do this because when I tride to go to the JSON serializer a bunch of tests started failing because various parts of our code are putting things into the session that are not JSON serializable. We can't keep using the default pickle serializer because it defaluts to using the highest available protocol and that will cause issues with the python 2 to 3 upgrade since both will be running in production at the same time. We need to use a version of the pickle protocol that both can use interchangably. We also need to make sure we read with latin1 encoding to make datetimes work correctly between the two versions of python. --- cms/envs/common.py | 1 + lms/envs/common.py | 1 + openedx/core/lib/session_serializers.py | 37 +++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 openedx/core/lib/session_serializers.py diff --git a/cms/envs/common.py b/cms/envs/common.py index bf60eee34b..a704f2608f 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -829,6 +829,7 @@ COURSES_WITH_UNSAFE_CODE = [] DEBUG = False SESSION_COOKIE_SECURE = False SESSION_SAVE_EVERY_REQUEST = False +SESSION_SERIALIZER = 'openedx.core.lib.session_serializers.PickleV2Serializer' SESSION_COOKIE_DOMAIN = "" SESSION_COOKIE_NAME = 'sessionid' diff --git a/lms/envs/common.py b/lms/envs/common.py index ef38521367..03f5cac060 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1101,6 +1101,7 @@ DEBUG = False USE_TZ = True SESSION_COOKIE_SECURE = False SESSION_SAVE_EVERY_REQUEST = False +SESSION_SERIALIZER = 'openedx.core.lib.session_serializers.PickleV2Serializer' SESSION_COOKIE_DOMAIN = "" SESSION_COOKIE_NAME = 'sessionid' diff --git a/openedx/core/lib/session_serializers.py b/openedx/core/lib/session_serializers.py new file mode 100644 index 0000000000..c1ff9ae51d --- /dev/null +++ b/openedx/core/lib/session_serializers.py @@ -0,0 +1,37 @@ +""" +Custom session serializer to deal with going from python2 and python3. +""" +import pickle +import six + + +class PickleV2Serializer(object): + """ + Lock the pickle serializer to version 2 of the protocol + because we don't want python 2 to be able to read session + data written by python3 while both are running at the same + time in production. + + Based on the PickleSerializer built into django: + https://github.com/django/django/blob/master/django/contrib/sessions/serializers.py + """ + + protocol = 2 + + def dumps(self, obj): + """ + Return a pickled representation of object. + """ + return pickle.dumps(obj, self.protocol) + + def loads(self, data): + """ + Return a python object from pickled data. + """ + if six.PY2: + # Params used below don't exist in python 2 + return pickle.loads(data) + else: + # See notes here about pickling python2 objects in python3 + # https://docs.python.org/3/library/pickle.html#pickle.Unpickler + return pickle.loads(data, encoding='latin1') # pylint: disable=unexpected-keyword-arg