Commit bb56a5d9 by Calen Pennington

Merge pull request #58 from edx/dont-change-user-id-in-session

Don't allow the user id to change in a session loaded from storage.
parents 496022a4 6eace27f
......@@ -42,7 +42,7 @@ DEBUG = False
TEMPLATE_DEBUG = False
EMAIL_BACKEND = 'django_ses.SESBackend'
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_ENGINE = 'openedx.core.djangoapps.safe_sessions.backends.cache'
# IMPORTANT: With this enabled, the server must always be behind a proxy that
# strips the header HTTP_X_FORWARDED_PROTO from client requests. Otherwise,
......
......@@ -394,6 +394,7 @@ DEBUG = False
TEMPLATE_DEBUG = False
SESSION_COOKIE_SECURE = False
SESSION_SAVE_EVERY_REQUEST = False
SESSION_ENGINE = 'openedx.core.djangoapps.safe_sessions.backends.db'
# Site info
SITE_ID = 1
......
......@@ -62,7 +62,7 @@ DEBUG = False
TEMPLATE_DEBUG = False
EMAIL_BACKEND = 'django_ses.SESBackend'
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_ENGINE = 'openedx.core.djangoapps.safe_sessions.backends.cache'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
##############################################################
......
......@@ -73,7 +73,7 @@ def gen_all_identities():
@ddt
@override_settings(SESSION_ENGINE='django.contrib.sessions.backends.cache')
@override_settings(SESSION_ENGINE='openedx.core.djangoapps.safe_sessions.backends.cache')
class ShibSPTest(SharedModuleStoreTestCase):
"""
Tests for the Shibboleth SP, which communicates via request.META
......
......@@ -47,7 +47,7 @@ DEBUG = False
TEMPLATE_DEBUG = False
EMAIL_BACKEND = 'django_ses.SESBackend'
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_ENGINE = 'openedx.core.djangoapps.safe_sessions.backends.cache'
# IMPORTANT: With this enabled, the server must always be behind a proxy that
# strips the header HTTP_X_FORWARDED_PROTO from client requests. Otherwise,
......
......@@ -802,6 +802,7 @@ TEMPLATE_DEBUG = False
USE_TZ = True
SESSION_COOKIE_SECURE = False
SESSION_SAVE_EVERY_REQUEST = False
SESSION_ENGINE = 'openedx.core.djangoapps.safe_sessions.backends.db'
# CMS base
CMS_BASE = 'localhost:8001'
......
......@@ -48,7 +48,7 @@ CACHES = {
}
}
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_ENGINE = 'openedx.core.djangoapps.safe_sessions.backends.cache'
################################ DEBUG TOOLBAR #################################
......
......@@ -61,7 +61,7 @@ DEBUG = False
TEMPLATE_DEBUG = False
EMAIL_BACKEND = 'django_ses.SESBackend'
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_ENGINE = 'openedx.core.djangoapps.safe_sessions.backends.cache'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
# IMPORTANT: With this enabled, the server must always be behind a proxy that
......
from django.contrib.auth import SESSION_KEY
class SessionUserChanged(Exception):
def __init__(self, key, new, stored):
self.key = key
self.new = new
self.stored = stored
super(SessionUserChanged, self).__init__(
"Cannot change session {} from user {} to user {}".format(
self.key,
self.stored,
self.new,
)
)
class SafeSessionMixin(object):
"""
Mixin to prevent a session from being changed from one userid to another.
"""
def __init__(self, *args, **kwargs):
self.__stored_user = None
super(SafeSessionMixin, self).__init__(*args, **kwargs)
def __setitem__(self, key, value):
if (
key == SESSION_KEY and
self.__stored_user is not None and
value != self.__stored_user
):
raise SessionUserChanged(self.session_key, value, self.__stored_user)
return super(SafeSessionMixin, self).__setitem__(key, value)
def pop(self, key, *args):
if key == SESSION_KEY and self.__stored_user is None:
self.__stored_user = self._session.get(SESSION_KEY)
return super(SafeSessionMixin, self).pop(key, *args)
def setdefault(self, key, value):
if (
key == SESSION_KEY and
self.__stored_user is not None and
value != self.__stored_user
):
raise SessionUserChanged(self.session_key, value, self.__stored_user)
return super(SafeSessionMixin, self).setdefault(key, value)
def update(self, dict_):
if (
SESSION_KEY in dict_ and
self.__stored_user is not None and
dict_[SESSION_KEY] != self.__stored_user
):
raise SessionUserChanged(self.session_key, dict_[SESSION_KEY], self.__stored_user)
return super(SafeSessionMixin, self).save(must_create=must_create)
def clear(self):
super(SafeSessionMixin, self).clear()
self.__stored_user = None
def save(self, must_create=False):
"""
Saves the session data. If 'must_create' is True, a new session object
is created (otherwise a CreateError exception is raised). Otherwise,
save() can update an existing object with the same key.
"""
if (
SESSION_KEY in self._session and
self.__stored_user is not None and
self._session[SESSION_KEY] != self.__stored_user
):
raise SessionUserChanged(self.session_key, self._session[SESSION_KEY], self.__stored_user)
return super(SafeSessionMixin, self).save(must_create=must_create)
def load(self):
"""
Loads the session data and returns a dictionary.
"""
session_data = super(SafeSessionMixin, self).load()
self.__stored_user = session_data.get(SESSION_KEY)
return session_data
from django.contrib.sessions.backends.cache import SessionStore
from .base import SafeSessionMixin
class SessionStore(SafeSessionMixin, SessionStore):
pass
from django.contrib.sessions.backends.cached_db import SessionStore
from .base import SafeSessionMixin
class SessionStore(SafeSessionMixin, SessionStore):
pass
from django.contrib.sessions.backends.db import SessionStore
from .base import SafeSessionMixin
class SessionStore(SafeSessionMixin, SessionStore):
pass
from django.contrib.sessions.backends.file import SessionStore
from .base import SafeSessionMixin
class SessionStore(SafeSessionMixin, SessionStore):
pass
from django.contrib.sessions.backends.signed_cookies import SessionStore
from .base import SafeSessionMixin
class SessionStore(SafeSessionMixin, SessionStore):
pass
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment