#32191: Not RFC Compliant Cookie handling ----------------------------------+-------------------------------------- Reporter: Nico Giefing | Owner: nobody Type: Bug | Status: new Component: HTTP handling | Version: 3.1 Severity: Normal | Resolution: Keywords: Cookie malformed | Triage Stage: Unreviewed Has patch: 0 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 ----------------------------------+--------------------------------------
Comment (by Florian Apolloner): An initial approach can look like this: {{{ diff --git a/django/contrib/messages/storage/cookie.py b/django/contrib/messages/storage/cookie.py index b51e292aa0..c75ed75940 100644 --- a/django/contrib/messages/storage/cookie.py +++ b/django/contrib/messages/storage/cookie.py @@ -1,5 +1,7 @@ import json +from urllib.parse import quote, unquote + from django.conf import settings from django.contrib.messages.storage.base import BaseStorage, Message from django.core import signing @@ -8,6 +10,9 @@ from django.utils.crypto import constant_time_compare, salted_hmac from django.utils.safestring import SafeData, mark_safe +SAFE_COOKIE_CHARS = "!#$%&'()*+/:<=>?@[]^`{|}" + + class MessageEncoder(json.JSONEncoder): """ Compactly serialize instances of the ``Message`` class as JSON. @@ -24,6 +29,9 @@ class MessageEncoder(json.JSONEncoder): return message return super().default(obj) + def encode(self, obj): + return quote(super().encode(obj), safe=SAFE_COOKIE_CHARS) + class MessageDecoder(json.JSONDecoder): """ @@ -43,7 +51,7 @@ class MessageDecoder(json.JSONDecoder): return obj def decode(self, s, **kwargs): - decoded = super().decode(s, **kwargs) + decoded = super().decode(unquote(s), **kwargs) return self.process_messages(decoded) diff --git a/tests/messages_tests/test_cookie.py b/tests/messages_tests/test_cookie.py index 5d5fb42d67..af7f36f8d0 100644 --- a/tests/messages_tests/test_cookie.py +++ b/tests/messages_tests/test_cookie.py @@ -182,3 +182,12 @@ class CookieTests(BaseTests, SimpleTestCase): self.assertEqual(decoded, messages) storage_default = self.get_storage() self.assertNotEqual(encoded, storage_default._encode(messages)) + + def test_rfc_6265_encoding(self): + storage = self.storage_class(self.get_request()) + msg_1 = Message(constants.INFO, 'Test me') + msg_2 = Message(constants.INFO, 'Test me \\again') + example_messages = [msg_1, msg_2] + encoded = storage._encode(example_messages) + expected = '[[%22__json_message%22%2C0%2C20%2C%22Test%20me%22]%2C[%22__json_message%22%2C0%2C20%2C%22Test%20me%20%5C%5Cagain%22]]' + self.assertEqual(encoded.split(':')[0], expected) }}} That said, this makes messages quite a bit longer :/ -- Ticket URL: <https://code.djangoproject.com/ticket/32191#comment:6> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/063.4cc98fb67cf9090a9d10053933749eb2%40djangoproject.com.