Ticket #16199: 16199.3.diff

File 16199.3.diff, 6.2 KB (added by jezdez, 4 years ago)

updated backend to use pickle

  • new file django/contrib/sessions/backends/cookies.py

    diff --git a/django/contrib/sessions/backends/cookies.py b/django/contrib/sessions/backends/cookies.py
    new file mode 100644
    index 0000000..0eb9071
    - +  
     1import zlib
     2try:
     3    import cPickle as pickle
     4except ImportError:
     5    import pickle
     6
     7from django.conf import settings
     8from django.core import signing
     9from django.utils.encoding import smart_str
     10
     11from django.contrib.sessions.backends.base import SessionBase
     12
     13
     14class SessionStore(SessionBase):
     15    salt = 'django.contrib.sessions.backends.cookies'
     16
     17    def load(self):
     18        """
     19        We load the data from the key itself instead of fetching from some
     20        external data store. Opposite of _get_session_key(), raises
     21        BadSignature if signature fails.
     22        """
     23        signer = signing.TimestampSigner(salt=self.salt)
     24        try:
     25            base64d = signer.unsign(
     26                self._session_key, max_age=settings.SESSION_COOKIE_AGE)
     27            pickled = signing.b64_decode(smart_str(base64d))
     28            return pickle.loads(zlib.decompress(pickled))
     29        except (signing.BadSignature, ValueError):
     30            self.create()
     31            return {}
     32
     33    def create(self):
     34        """
     35        To create a new key, we simply make sure that the modified flag is set
     36        so that the cookie is set on the client for the current request.
     37        """
     38        self.modified = True
     39
     40    def save(self):
     41        """
     42        To save, we get the session key as a securely signed string and then
     43        set the modified flag so that the cookie is set on the client for the
     44        current request.
     45        """
     46        self._session_key = self._get_session_key()
     47        self.modified = True
     48
     49    def exists(self, session_key=None):
     50        """
     51        This method makes sense when you're talking to a shared resource, but
     52        it doesn't matter when you're storing the information in the client's
     53        cookie.
     54        """
     55        return False
     56
     57    def delete(self, session_key=None):
     58        """
     59        To delete, we clear the session key and the underlying data structure
     60        and set the modified flag so that the cookie is set on the client for
     61        the current request.
     62        """
     63        self._session_key = ''
     64        self._session_cache = {}
     65        self.modified = True
     66
     67    def cycle_key(self):
     68        """
     69        Keeps the same data but with a new key.  To do this, we just have to
     70        call ``save()`` and it will automatically save a cookie with a new key
     71        at the end of the request.
     72        """
     73        self.save()
     74
     75    def _get_session_key(self):
     76        """
     77        Most session backends don't need to override this method, but we do,
     78        because instead of generating a random string, we want to actually
     79        generate a secure url-safe Base64-encoded string of data as our
     80        session key.
     81        """
     82        payload = getattr(self, '_session_cache', {})
     83        pickled = pickle.dumps(payload, pickle.HIGHEST_PROTOCOL)
     84        base64d = signing.b64_encode(zlib.compress(pickled))
     85        return signing.TimestampSigner(salt=self.salt).sign(base64d)
     86
     87    def _set_session_key(self, session_key):
     88        self._session_key = session_key
     89
     90    session_key = property(_get_session_key, _set_session_key)
  • django/contrib/sessions/tests.py

    diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py
    index 2eb43f3..55d69fd 100644
    a b from django.contrib.sessions.backends.db import SessionStore as DatabaseSession 
    77from django.contrib.sessions.backends.cache import SessionStore as CacheSession
    88from django.contrib.sessions.backends.cached_db import SessionStore as CacheDBSession
    99from django.contrib.sessions.backends.file import SessionStore as FileSession
     10from django.contrib.sessions.backends.cookies import SessionStore as CookieSession
    1011from django.contrib.sessions.models import Session
    1112from django.contrib.sessions.middleware import SessionMiddleware
    1213from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
    class SessionMiddlewareTests(unittest.TestCase): 
    361362        # Handle the response through the middleware
    362363        response = middleware.process_response(request, response)
    363364        self.assertTrue(response.cookies[settings.SESSION_COOKIE_NAME]['httponly'])
     365
     366
     367class CookieSessionTests(SessionTestsMixin, TestCase):
     368
     369    backend = CookieSession
     370
     371    def test_save(self):
     372        """
     373        This test tested exists() in the other session backends, but that
     374        doesn't make sense for us.
     375        """
     376        pass
  • django/core/signing.py

    diff --git a/django/core/signing.py b/django/core/signing.py
    index 3165cf8..224d942 100644
    a b class TimestampSigner(Signer): 
    161161    def __init__(self, *args, **kwargs):
    162162        self.time_func = kwargs.pop('time', time.time)
    163163        super(TimestampSigner, self).__init__(*args, **kwargs)
    164    
     164
    165165    def timestamp(self):
    166166        return baseconv.base62.encode(int(self.time_func() * 10000))
    167167
  • docs/topics/http/sessions.txt

    diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
    index 8529f53..4632641 100644
    a b defaults to output from ``tempfile.gettempdir()``, most likely ``/tmp``) to 
    9595control where Django stores session files. Be sure to check that your Web
    9696server has permissions to read and write to this location.
    9797
     98Using cookies-based sessions
     99----------------------------
     100
     101.. versionadded:: 1.4
     102
     103To use cookies-based sessions, set the :setting:`SESSION_ENGINE` setting to
     104``"django.contrib.sessions.backends.cookies"``. The session data will be
     105stored using Django's tools for :doc:`cryptographic signing </topics/signing>`
     106and the :setting:`SECRET_KEY` setting.
    98107
    99108Using sessions in views
    100109=======================
    Controls where Django stores session data. Valid values are: 
    420429    * ``'django.contrib.sessions.backends.file'``
    421430    * ``'django.contrib.sessions.backends.cache'``
    422431    * ``'django.contrib.sessions.backends.cached_db'``
     432    * ``'django.contrib.sessions.backends.cookies'``
    423433
    424434See `configuring the session engine`_ for more details.
    425435
Back to Top