Index: docs/topics/http/sessions.txt
===================================================================
--- docs/topics/http/sessions.txt (revision 16025)
+++ docs/topics/http/sessions.txt (working copy)
@@ -435,7 +435,10 @@
The domain to use for session cookies. Set this to a string such as
``".lawrence.com"`` (note the leading dot!) for cross-domain cookies, or use
-``None`` for a standard domain cookie.
+``None`` for a standard domain cookie. It should also have sufficient dots
+(``.``) to ensure it will be valid and sent to the server by browsers. So
+``".example.com"`` or ``"example.com"`` are good but avoid ``".localhost"`` or
+``"localhost"``.
SESSION_COOKIE_HTTPONLY
-----------------------
Index: docs/ref/settings.txt
===================================================================
--- docs/ref/settings.txt (revision 16025)
+++ docs/ref/settings.txt (working copy)
@@ -322,7 +322,10 @@
allowing cross-subdomain requests to be exluded from the normal cross site
request forgery protection. It should be set to a string such as
``".lawrence.com"`` to allow a POST request from a form on one subdomain to be
-accepted by accepted by a view served from another subdomain.
+accepted by accepted by a view served from another subdomain. It should also
+have sufficient dots (``.``) to ensure it will be valid and sent to the server
+by browsers. So ``".example.com"`` or ``"example.com"`` are good but avoid
+``".localhost"`` or ``"localhost"``.
.. setting:: CSRF_COOKIE_NAME
@@ -1480,7 +1483,10 @@
The domain to use for session cookies. Set this to a string such as
``".lawrence.com"`` for cross-domain cookies, or use ``None`` for a standard
-domain cookie. See the :doc:`/topics/http/sessions`.
+domain cookie. It should also have sufficient dots (``.``) to ensure it will be
+valid and sent to the server by browsers. So ``".example.com"`` or
+``"example.com"`` are good but avoid ``".localhost"`` or ``"localhost"``. See
+the :doc:`/topics/http/sessions`.
.. setting:: SESSION_COOKIE_HTTPONLY
Index: django/conf/__init__.py
===================================================================
--- django/conf/__init__.py (revision 16025)
+++ django/conf/__init__.py (working copy)
@@ -12,6 +12,7 @@
import warnings
from django.conf import global_settings
+from django.core.exceptions import ImproperlyConfigured
from django.utils.functional import LazyObject
from django.utils import importlib
@@ -70,6 +71,13 @@
if name in ("MEDIA_URL", "STATIC_URL") and value and not value.endswith('/'):
warnings.warn('If set, %s must end with a slash' % name,
DeprecationWarning)
+ if name in ("CSRF_COOKIE_DOMAIN", "SESSION_COOKIE_DOMAIN"):
+ if value is not None:
+ if (value.startswith('.') and value.count('.') < 2 or
+ '.' not in value):
+ raise ImproperlyConfigured('If set, %s should contain '
+ 'sufficient dots (.), e.g., ".example.com" or '
+ '"example.com"' % name)
object.__setattr__(self, name, value)
Index: tests/regressiontests/settings_tests/tests.py
===================================================================
--- tests/regressiontests/settings_tests/tests.py (revision 16025)
+++ tests/regressiontests/settings_tests/tests.py (working copy)
@@ -1,6 +1,7 @@
from django.conf import settings
from django.utils import unittest
from django.conf import settings, UserSettingsHolder, global_settings
+from django.core.exceptions import ImproperlyConfigured
class SettingsTests(unittest.TestCase):
@@ -76,3 +77,35 @@
self.settings_module.MEDIA_URL = 'http://media.foo.com/stupid//'
self.assertEqual('http://media.foo.com/stupid//',
self.settings_module.MEDIA_URL)
+
+
+class CookieDomainTests(unittest.TestCase):
+ setting_names = ('CSRF_COOKIE_DOMAIN', 'SESSION_COOKIE_DOMAIN')
+
+ def test_none(self):
+ for setting_name in self.setting_names:
+ setattr(settings, setting_name, None)
+
+ def test_empty(self):
+ for setting_name in self.setting_names:
+ self.assertRaises(ImproperlyConfigured, setattr, settings,
+ setting_name, '')
+
+ def test_startswith_dot_too_few(self):
+ for setting_name in self.setting_names:
+ self.assertRaises(ImproperlyConfigured, setattr, settings,
+ setting_name, '.localhost')
+
+ def test_startswith_dot_sufficient_dots(self):
+ for setting_name in self.setting_names:
+ setattr(settings, setting_name, '.example.com')
+
+ def test_not_startswith_dot_too_few(self):
+ for setting_name in self.setting_names:
+ self.assertRaises(ImproperlyConfigured, setattr, settings,
+ setting_name, 'localhost')
+
+ def test_not_startswith_dot_sufficient_dots(self):
+ for setting_name in self.setting_names:
+ setattr(settings, setting_name, 'example.com')
+