瀏覽代碼

Fixed #30304 -- Added support for the HttpOnly, SameSite, and Secure flags on language cookies.

Ran Benita 6 年之前
父節點
當前提交
19fc6376ce

+ 3 - 0
django/conf/global_settings.py

@@ -154,6 +154,9 @@ LANGUAGE_COOKIE_NAME = 'django_language'
 LANGUAGE_COOKIE_AGE = None
 LANGUAGE_COOKIE_DOMAIN = None
 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

+ 3 - 0
django/views/i18n.py

@@ -55,6 +55,9 @@ def set_language(request):
                 max_age=settings.LANGUAGE_COOKIE_AGE,
                 path=settings.LANGUAGE_COOKIE_PATH,
                 domain=settings.LANGUAGE_COOKIE_DOMAIN,
+                secure=settings.LANGUAGE_COOKIE_SECURE,
+                httponly=settings.LANGUAGE_COOKIE_HTTPONLY,
+                samesite=settings.LANGUAGE_COOKIE_SAMESITE,
             )
     return response
 

+ 45 - 0
docs/ref/settings.txt

@@ -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
 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
 
 ``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
 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
 
 ``LANGUAGES``
@@ -3402,8 +3444,11 @@ Globalization (``i18n``/``l10n``)
 * :setting:`LANGUAGE_CODE`
 * :setting:`LANGUAGE_COOKIE_AGE`
 * :setting:`LANGUAGE_COOKIE_DOMAIN`
+* :setting:`LANGUAGE_COOKIE_HTTPONLY`
 * :setting:`LANGUAGE_COOKIE_NAME`
 * :setting:`LANGUAGE_COOKIE_PATH`
+* :setting:`LANGUAGE_COOKIE_SAMESITE`
+* :setting:`LANGUAGE_COOKIE_SECURE`
 * :setting:`LANGUAGES`
 * :setting:`LANGUAGES_BIDI`
 * :setting:`LOCALE_PATHS`

+ 5 - 1
docs/releases/3.0.txt

@@ -153,7 +153,11 @@ Generic Views
 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
 ~~~~~~~~~~~~~~~~~~~

+ 3 - 0
docs/topics/i18n/translation.txt

@@ -1896,7 +1896,10 @@ A number of settings can be used to adjust language cookie options:
 * :setting:`LANGUAGE_COOKIE_NAME`
 * :setting:`LANGUAGE_COOKIE_AGE`
 * :setting:`LANGUAGE_COOKIE_DOMAIN`
+* :setting:`LANGUAGE_COOKIE_HTTPONLY`
 * :setting:`LANGUAGE_COOKIE_PATH`
+* :setting:`LANGUAGE_COOKIE_SAMESITE`
+* :setting:`LANGUAGE_COOKIE_SECURE`
 
 Implementation notes
 ====================

+ 9 - 0
tests/view_tests/tests/test_i18n.py

@@ -45,6 +45,9 @@ class SetLanguageTests(TestCase):
         self.assertEqual(language_cookie['domain'], '')
         self.assertEqual(language_cookie['path'], '/')
         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):
         """
@@ -175,6 +178,9 @@ class SetLanguageTests(TestCase):
             'LANGUAGE_COOKIE_AGE': 3600 * 7 * 2,
             'LANGUAGE_COOKIE_DOMAIN': '.example.com',
             'LANGUAGE_COOKIE_PATH': '/test/',
+            'LANGUAGE_COOKIE_HTTPONLY': True,
+            'LANGUAGE_COOKIE_SAMESITE': 'Strict',
+            'LANGUAGE_COOKIE_SECURE': True,
         }
         with self.settings(**test_settings):
             post_data = {'language': 'pl', 'next': '/views/'}
@@ -184,6 +190,9 @@ class SetLanguageTests(TestCase):
             self.assertEqual(language_cookie['domain'], '.example.com')
             self.assertEqual(language_cookie['path'], '/test/')
             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):
         """