Code

Ticket #16199: 16199.1.diff

File 16199.1.diff, 5.1 KB (added by jezdez, 3 years ago)

Ported over Eric's backend

Line 
1diff --git a/django/contrib/sessions/backends/cookies.py b/django/contrib/sessions/backends/cookies.py
2new file mode 100644
3index 0000000..550d26b
4--- /dev/null
5+++ b/django/contrib/sessions/backends/cookies.py
6@@ -0,0 +1,72 @@
7+from django.conf import settings
8+from django.core import signing
9+
10+from django.contrib.sessions.backends.base import SessionBase
11+
12+
13+class SessionStore(SessionBase):
14+
15+    def load(self):
16+        """
17+        We load the data from the key itself instead of fetching from some
18+        external data store.
19+        """
20+        try:
21+            return signing.loads(self._session_key,
22+                max_age=settings.SESSION_COOKIE_AGE,
23+                salt='django.contrib.sessions.backends.cookies')
24+        except (signing.BadSignature, ValueError):
25+            self.create()
26+            return {}
27+
28+    def create(self):
29+        """
30+        To create a new key, we simply make sure that the modified flag is set
31+        so that the cookie is set on the client for the current request.
32+        """
33+        self.modified = True
34+
35+    def save(self):
36+        """
37+        To save, we get the session key as a securely signed string and then
38+        set the modified flag so that the cookie is set on the client for the
39+        current request.
40+        """
41+        self._session_key = self._get_session_key()
42+        self.modified = True
43+
44+    def exists(self, session_key=None):
45+        """
46+        This method makes sense when you're talking to a shared resource, but
47+        it doesn't matter when you're storing the information in the client's
48+        cookie.
49+        """
50+        return False
51+
52+    def delete(self, session_key=None):
53+        """
54+        To delete, we clear the session key and the underlying data structure
55+        and set the modified flag so that the cookie is set on the client for
56+        the current request.
57+        """
58+        self._session_key = ''
59+        self._session_cache = {}
60+        self.modified = True
61+
62+    def cycle_key(self):
63+        """
64+        Keeps the same data but with a new key.  To do this, we just have to
65+        call ``save()`` and it will automatically save a cookie with a new key
66+        at the end of the request.
67+        """
68+        self.save()
69+
70+    def _get_session_key(self):
71+        """
72+        Most session backends don't need to override this method, but we do,
73+        because instead of generating a random string, we want to actually
74+        generate a secure url-safe Base64-encoded string of data as our
75+        session key.
76+        """
77+        return signing.dumps(getattr(self, '_session_cache', {}),
78+            salt='django.contrib.sessions.backends.cookies', compress=True)
79diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py
80index 2eb43f3..af4c37d 100644
81--- a/django/contrib/sessions/tests.py
82+++ b/django/contrib/sessions/tests.py
83@@ -7,6 +7,7 @@ from django.contrib.sessions.backends.db import SessionStore as DatabaseSession
84 from django.contrib.sessions.backends.cache import SessionStore as CacheSession
85 from django.contrib.sessions.backends.cached_db import SessionStore as CacheDBSession
86 from django.contrib.sessions.backends.file import SessionStore as FileSession
87+from django.contrib.sessions.backends.cookies import SessionStore as CookieSession
88 from django.contrib.sessions.models import Session
89 from django.contrib.sessions.middleware import SessionMiddleware
90 from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
91@@ -361,3 +362,15 @@ class SessionMiddlewareTests(unittest.TestCase):
92         # Handle the response through the middleware
93         response = middleware.process_response(request, response)
94         self.assertTrue(response.cookies[settings.SESSION_COOKIE_NAME]['httponly'])
95+
96+
97+class CacheDBSessionTests(SessionTestsMixin, TestCase):
98+
99+    backend = CookieSession
100+
101+    def test_save(self):
102+        """
103+        This test tested exists() in the other session backends, but that
104+        doesn't make sense for us.
105+        """
106+        pass
107diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
108index 8529f53..4632641 100644
109--- a/docs/topics/http/sessions.txt
110+++ b/docs/topics/http/sessions.txt
111@@ -95,6 +95,15 @@ defaults to output from ``tempfile.gettempdir()``, most likely ``/tmp``) to
112 control where Django stores session files. Be sure to check that your Web
113 server has permissions to read and write to this location.
114 
115+Using cookies-based sessions
116+----------------------------
117+
118+.. versionadded:: 1.4
119+
120+To use cookies-based sessions, set the :setting:`SESSION_ENGINE` setting to
121+``"django.contrib.sessions.backends.cookies"``. The session data will be
122+stored using Django's tools for :doc:`cryptographic signing </topics/signing>`
123+and the :setting:`SECRET_KEY` setting.
124 
125 Using sessions in views
126 =======================
127@@ -420,6 +429,7 @@ Controls where Django stores session data. Valid values are:
128     * ``'django.contrib.sessions.backends.file'``
129     * ``'django.contrib.sessions.backends.cache'``
130     * ``'django.contrib.sessions.backends.cached_db'``
131+    * ``'django.contrib.sessions.backends.cookies'``
132 
133 See `configuring the session engine`_ for more details.
134