diff --git a/django/contrib/messages/storage/cookie.py b/django/contrib/messages/storage/cookie.py index 619c69249e..8c394d2046 100644 --- a/django/contrib/messages/storage/cookie.py +++ b/django/contrib/messages/storage/cookie.py @@ -79,7 +79,9 @@ class CookieStorage(BaseStorage): """ if encoded_data: response.set_cookie(self.cookie_name, encoded_data, - domain=settings.SESSION_COOKIE_DOMAIN) + domain=settings.SESSION_COOKIE_DOMAIN, + secure=settings.SESSION_COOKIE_SECURE or None, + httponly=settings.SESSION_COOKIE_HTTPONLY or None) else: response.delete_cookie(self.cookie_name, domain=settings.SESSION_COOKIE_DOMAIN) diff --git a/django/contrib/messages/tests/test_cookie.py b/django/contrib/messages/tests/test_cookie.py index 5871ecc773..e57cc33946 100644 --- a/django/contrib/messages/tests/test_cookie.py +++ b/django/contrib/messages/tests/test_cookie.py @@ -41,7 +41,7 @@ def stored_cookie_messages_count(storage, response): return len(data) -@override_settings(SESSION_COOKIE_DOMAIN='.example.com') +@override_settings(SESSION_COOKIE_DOMAIN='.example.com', SESSION_COOKIE_SECURE=True, SESSION_COOKIE_HTTPONLY=True) class CookieTest(BaseTests, TestCase): storage_class = CookieStorage @@ -56,10 +56,10 @@ class CookieTest(BaseTests, TestCase): # Test that the message actually contains what we expect. self.assertEqual(list(storage), example_messages) - def test_domain(self): + def test_cookie_setings(self): """ - Ensure that CookieStorage honors SESSION_COOKIE_DOMAIN. - Refs #15618. + Ensure that CookieStorage honors SESSION_COOKIE_DOMAIN, SESSION_COOKIE_SECURE and SESSION_COOKIE_HTTPONLY + Refs #15618 and #20972. """ # Test before the messages have been consumed storage = self.get_storage() @@ -69,8 +69,10 @@ class CookieTest(BaseTests, TestCase): self.assertTrue('test' in response.cookies['messages'].value) self.assertEqual(response.cookies['messages']['domain'], '.example.com') self.assertEqual(response.cookies['messages']['expires'], '') + self.assertEqual(response.cookies['messages']['secure'], True) + self.assertEqual(response.cookies['messages']['httponly'], True) - # Test after the messages have been consumed + # Test deletion of the cookie (storing with an empty value) after the messages have been consumed storage = self.get_storage() response = self.get_response() storage.add(constants.INFO, 'test') diff --git a/docs/ref/contrib/messages.txt b/docs/ref/contrib/messages.txt index 2014c7c183..c1995b6d39 100644 --- a/docs/ref/contrib/messages.txt +++ b/docs/ref/contrib/messages.txt @@ -376,3 +376,12 @@ behavior: * :setting:`MESSAGE_LEVEL` * :setting:`MESSAGE_STORAGE` * :setting:`MESSAGE_TAGS` + +.. versionadded:: 1.7 + +For backends that use cookies, the settings for the cookie are taken from +the session cookie settings: + +* :setting:`SESSION_COOKIE_DOMAIN` +* :setting:`SESSION_COOKIE_SECURE` +* :setting:`SESSION_COOKIE_HTTPONLY` diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 2f531803bc..b0bc020f47 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -2266,7 +2266,8 @@ See :ref:`message storage backends ` for more details. The backends that use cookies -- :class:`~django.contrib.messages.storage.cookie.CookieStorage` and :class:`~django.contrib.messages.storage.fallback.FallbackStorage` -- -use the value of :setting:`SESSION_COOKIE_DOMAIN` when setting their cookies. +use the value of :setting:`SESSION_COOKIE_DOMAIN`, :setting:`SESSION_COOKIE_SECURE` +and :setting:`SESSION_COOKIE_HTTPONLY` when setting their cookies. .. setting:: MESSAGE_TAGS @@ -2342,6 +2343,8 @@ standard domain cookies, existing user cookies will be set to the old domain. This may result in them being unable to log in as long as these cookies persist. +This setting also affects cookies set by :mod:`django.contrib.messages`. + .. setting:: SESSION_COOKIE_HTTPONLY SESSION_COOKIE_HTTPONLY @@ -2359,6 +2362,10 @@ consistently by all browsers. However, when it is honored, it can be a useful way to mitigate the risk of client side script accessing the protected cookie data. +.. versionadded:: 1.7 + +This setting also affects cookies set by :mod:`django.contrib.messages`. + .. _HTTPOnly: https://www.owasp.org/index.php/HTTPOnly .. setting:: SESSION_COOKIE_NAME @@ -2396,6 +2403,10 @@ Whether to use a secure cookie for the session cookie. If this is set to ``True``, the cookie will be marked as "secure," which means browsers may ensure that the cookie is only sent under an HTTPS connection. +.. versionadded:: 1.7 + +This setting also affects cookies set by :mod:`django.contrib.messages`. + .. setting:: SESSION_ENGINE SESSION_ENGINE diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index 4c295f58e0..ea4b09d831 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -214,6 +214,10 @@ Minor features * The :ttag:`widthratio` template tag now accepts an "as" parameter to capture the result in a variable. +* The backends for :mod:`django.contrib.messages` that use cookies, will now + follow the :setting:`SESSION_COOKIE_SECURE` and + :setting:`SESSION_COOKIE_HTTPONLY` settings. + Backwards incompatible changes in 1.7 =====================================