Fixed #30304 -- Added support for the HttpOnly, SameSite, and Secure flags on language cookies.
This commit is contained in:
parent
cef3f2d3c6
commit
19fc6376ce
|
@ -154,6 +154,9 @@ LANGUAGE_COOKIE_NAME = 'django_language'
|
||||||
LANGUAGE_COOKIE_AGE = None
|
LANGUAGE_COOKIE_AGE = None
|
||||||
LANGUAGE_COOKIE_DOMAIN = None
|
LANGUAGE_COOKIE_DOMAIN = None
|
||||||
LANGUAGE_COOKIE_PATH = '/'
|
LANGUAGE_COOKIE_PATH = '/'
|
||||||
|
LANGUAGE_COOKIE_SECURE = False
|
||||||
|
LANGUAGE_COOKIE_HTTPONLY = False
|
||||||
|
LANGUAGE_COOKIE_SAMESITE = None
|
||||||
|
|
||||||
|
|
||||||
# If you set this to True, Django will format dates, numbers and calendars
|
# If you set this to True, Django will format dates, numbers and calendars
|
||||||
|
|
|
@ -55,6 +55,9 @@ def set_language(request):
|
||||||
max_age=settings.LANGUAGE_COOKIE_AGE,
|
max_age=settings.LANGUAGE_COOKIE_AGE,
|
||||||
path=settings.LANGUAGE_COOKIE_PATH,
|
path=settings.LANGUAGE_COOKIE_PATH,
|
||||||
domain=settings.LANGUAGE_COOKIE_DOMAIN,
|
domain=settings.LANGUAGE_COOKIE_DOMAIN,
|
||||||
|
secure=settings.LANGUAGE_COOKIE_SECURE,
|
||||||
|
httponly=settings.LANGUAGE_COOKIE_HTTPONLY,
|
||||||
|
samesite=settings.LANGUAGE_COOKIE_SAMESITE,
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
|
@ -1766,6 +1766,21 @@ permanently (via the :setting:`LANGUAGE_COOKIE_NAME` setting) and to add
|
||||||
a middleware that copies the value from the old cookie to a new one and then
|
a middleware that copies the value from the old cookie to a new one and then
|
||||||
deletes the old one.
|
deletes the old one.
|
||||||
|
|
||||||
|
.. setting:: LANGUAGE_COOKIE_HTTPONLY
|
||||||
|
|
||||||
|
``LANGUAGE_COOKIE_HTTPONLY``
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
Whether to use ``HttpOnly`` flag on the language cookie. If this is set to
|
||||||
|
``True``, client-side JavaScript will not to be able to access the language
|
||||||
|
cookie.
|
||||||
|
|
||||||
|
See :setting:`SESSION_COOKIE_HTTPONLY` for details on ``HttpOnly``.
|
||||||
|
|
||||||
.. setting:: LANGUAGE_COOKIE_NAME
|
.. setting:: LANGUAGE_COOKIE_NAME
|
||||||
|
|
||||||
``LANGUAGE_COOKIE_NAME``
|
``LANGUAGE_COOKIE_NAME``
|
||||||
|
@ -1800,6 +1815,33 @@ permanently (via the :setting:`LANGUAGE_COOKIE_NAME` setting), and to add
|
||||||
a middleware that copies the value from the old cookie to a new one and then
|
a middleware that copies the value from the old cookie to a new one and then
|
||||||
deletes the one.
|
deletes the one.
|
||||||
|
|
||||||
|
.. setting:: LANGUAGE_COOKIE_SAMESITE
|
||||||
|
|
||||||
|
``LANGUAGE_COOKIE_SAMESITE``
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
|
||||||
|
Default: ``None``
|
||||||
|
|
||||||
|
The value of the `SameSite`_ flag on the language cookie. This flag prevents the
|
||||||
|
cookie from being sent in cross-site requests.
|
||||||
|
|
||||||
|
See :setting:`SESSION_COOKIE_SAMESITE` for details about ``SameSite``.
|
||||||
|
|
||||||
|
.. setting:: LANGUAGE_COOKIE_SECURE
|
||||||
|
|
||||||
|
``LANGUAGE_COOKIE_SECURE``
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
Whether to use a secure cookie for the language 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.
|
||||||
|
|
||||||
.. setting:: LANGUAGES
|
.. setting:: LANGUAGES
|
||||||
|
|
||||||
``LANGUAGES``
|
``LANGUAGES``
|
||||||
|
@ -3402,8 +3444,11 @@ Globalization (``i18n``/``l10n``)
|
||||||
* :setting:`LANGUAGE_CODE`
|
* :setting:`LANGUAGE_CODE`
|
||||||
* :setting:`LANGUAGE_COOKIE_AGE`
|
* :setting:`LANGUAGE_COOKIE_AGE`
|
||||||
* :setting:`LANGUAGE_COOKIE_DOMAIN`
|
* :setting:`LANGUAGE_COOKIE_DOMAIN`
|
||||||
|
* :setting:`LANGUAGE_COOKIE_HTTPONLY`
|
||||||
* :setting:`LANGUAGE_COOKIE_NAME`
|
* :setting:`LANGUAGE_COOKIE_NAME`
|
||||||
* :setting:`LANGUAGE_COOKIE_PATH`
|
* :setting:`LANGUAGE_COOKIE_PATH`
|
||||||
|
* :setting:`LANGUAGE_COOKIE_SAMESITE`
|
||||||
|
* :setting:`LANGUAGE_COOKIE_SECURE`
|
||||||
* :setting:`LANGUAGES`
|
* :setting:`LANGUAGES`
|
||||||
* :setting:`LANGUAGES_BIDI`
|
* :setting:`LANGUAGES_BIDI`
|
||||||
* :setting:`LOCALE_PATHS`
|
* :setting:`LOCALE_PATHS`
|
||||||
|
|
|
@ -153,7 +153,11 @@ Generic Views
|
||||||
Internationalization
|
Internationalization
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* Added the :setting:`LANGUAGE_COOKIE_HTTPONLY`,
|
||||||
|
:setting:`LANGUAGE_COOKIE_SAMESITE`, and :setting:`LANGUAGE_COOKIE_SECURE`
|
||||||
|
settings to set the ``HttpOnly``, ``SameSite``, and ``Secure`` flags on
|
||||||
|
language cookies. The default values of these settings preserve the previous
|
||||||
|
behavior.
|
||||||
|
|
||||||
Management Commands
|
Management Commands
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -1896,7 +1896,10 @@ A number of settings can be used to adjust language cookie options:
|
||||||
* :setting:`LANGUAGE_COOKIE_NAME`
|
* :setting:`LANGUAGE_COOKIE_NAME`
|
||||||
* :setting:`LANGUAGE_COOKIE_AGE`
|
* :setting:`LANGUAGE_COOKIE_AGE`
|
||||||
* :setting:`LANGUAGE_COOKIE_DOMAIN`
|
* :setting:`LANGUAGE_COOKIE_DOMAIN`
|
||||||
|
* :setting:`LANGUAGE_COOKIE_HTTPONLY`
|
||||||
* :setting:`LANGUAGE_COOKIE_PATH`
|
* :setting:`LANGUAGE_COOKIE_PATH`
|
||||||
|
* :setting:`LANGUAGE_COOKIE_SAMESITE`
|
||||||
|
* :setting:`LANGUAGE_COOKIE_SECURE`
|
||||||
|
|
||||||
Implementation notes
|
Implementation notes
|
||||||
====================
|
====================
|
||||||
|
|
|
@ -45,6 +45,9 @@ class SetLanguageTests(TestCase):
|
||||||
self.assertEqual(language_cookie['domain'], '')
|
self.assertEqual(language_cookie['domain'], '')
|
||||||
self.assertEqual(language_cookie['path'], '/')
|
self.assertEqual(language_cookie['path'], '/')
|
||||||
self.assertEqual(language_cookie['max-age'], '')
|
self.assertEqual(language_cookie['max-age'], '')
|
||||||
|
self.assertEqual(language_cookie['httponly'], '')
|
||||||
|
self.assertEqual(language_cookie['samesite'], '')
|
||||||
|
self.assertEqual(language_cookie['secure'], '')
|
||||||
|
|
||||||
def test_setlang_unsafe_next(self):
|
def test_setlang_unsafe_next(self):
|
||||||
"""
|
"""
|
||||||
|
@ -175,6 +178,9 @@ class SetLanguageTests(TestCase):
|
||||||
'LANGUAGE_COOKIE_AGE': 3600 * 7 * 2,
|
'LANGUAGE_COOKIE_AGE': 3600 * 7 * 2,
|
||||||
'LANGUAGE_COOKIE_DOMAIN': '.example.com',
|
'LANGUAGE_COOKIE_DOMAIN': '.example.com',
|
||||||
'LANGUAGE_COOKIE_PATH': '/test/',
|
'LANGUAGE_COOKIE_PATH': '/test/',
|
||||||
|
'LANGUAGE_COOKIE_HTTPONLY': True,
|
||||||
|
'LANGUAGE_COOKIE_SAMESITE': 'Strict',
|
||||||
|
'LANGUAGE_COOKIE_SECURE': True,
|
||||||
}
|
}
|
||||||
with self.settings(**test_settings):
|
with self.settings(**test_settings):
|
||||||
post_data = {'language': 'pl', 'next': '/views/'}
|
post_data = {'language': 'pl', 'next': '/views/'}
|
||||||
|
@ -184,6 +190,9 @@ class SetLanguageTests(TestCase):
|
||||||
self.assertEqual(language_cookie['domain'], '.example.com')
|
self.assertEqual(language_cookie['domain'], '.example.com')
|
||||||
self.assertEqual(language_cookie['path'], '/test/')
|
self.assertEqual(language_cookie['path'], '/test/')
|
||||||
self.assertEqual(language_cookie['max-age'], 3600 * 7 * 2)
|
self.assertEqual(language_cookie['max-age'], 3600 * 7 * 2)
|
||||||
|
self.assertEqual(language_cookie['httponly'], True)
|
||||||
|
self.assertEqual(language_cookie['samesite'], 'Strict')
|
||||||
|
self.assertEqual(language_cookie['secure'], True)
|
||||||
|
|
||||||
def test_setlang_decodes_http_referer_url(self):
|
def test_setlang_decodes_http_referer_url(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue