Fixed #14134 - ability to set cookie 'path' and 'secure' attributes of CSRF cookie

Thanks to cfattarsi for the report and initial patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16200 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2011-05-09 23:00:22 +00:00
parent a75120927e
commit 8cbcf1d3a6
5 changed files with 76 additions and 8 deletions

View File

@ -484,9 +484,11 @@ PASSWORD_RESET_TIMEOUT_DAYS = 3
# rejected by the CSRF middleware. # rejected by the CSRF middleware.
CSRF_FAILURE_VIEW = 'django.views.csrf.csrf_failure' CSRF_FAILURE_VIEW = 'django.views.csrf.csrf_failure'
# Name and domain for CSRF cookie. # Settings for CSRF cookie.
CSRF_COOKIE_NAME = 'csrftoken' CSRF_COOKIE_NAME = 'csrftoken'
CSRF_COOKIE_DOMAIN = None CSRF_COOKIE_DOMAIN = None
CSRF_COOKIE_PATH = '/'
CSRF_COOKIE_SECURE = False
############ ############
# MESSAGES # # MESSAGES #

View File

@ -197,8 +197,12 @@ class CsrfViewMiddleware(object):
# Set the CSRF cookie even if it's already set, so we renew the expiry timer. # Set the CSRF cookie even if it's already set, so we renew the expiry timer.
response.set_cookie(settings.CSRF_COOKIE_NAME, response.set_cookie(settings.CSRF_COOKIE_NAME,
request.META["CSRF_COOKIE"], max_age = 60 * 60 * 24 * 7 * 52, request.META["CSRF_COOKIE"],
domain=settings.CSRF_COOKIE_DOMAIN) max_age = 60 * 60 * 24 * 7 * 52,
domain=settings.CSRF_COOKIE_DOMAIN,
path=settings.CSRF_COOKIE_PATH,
secure=settings.CSRF_COOKIE_SECURE
)
# Content varies with the CSRF cookie, so set the Vary header. # Content varies with the CSRF cookie, so set the Vary header.
patch_vary_headers(response, ('Cookie',)) patch_vary_headers(response, ('Cookie',))
response.csrf_processing_done = True response.csrf_processing_done = True

View File

@ -423,6 +423,31 @@ Default: ``'csrftoken'``
The name of the cookie to use for the CSRF authentication token. This can be The name of the cookie to use for the CSRF authentication token. This can be
whatever you want. whatever you want.
CSRF_COOKIE_PATH
----------------
.. versionadded:: 1.4
Default: ``'/'``
The path set on the CSRF cookie. This should either match the URL path of your
Django installation or be a parent of that path.
This is useful if you have multiple Django instances running under the same
hostname. They can use different cookie paths, and each instance will only see
its own CSRF cookie.
CSRF_COOKIE_SECURE
------------------
.. versionadded:: 1.4
Default: ``False``
Whether to use a secure cookie for the CSRF 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.
CSRF_FAILURE_VIEW CSRF_FAILURE_VIEW
----------------- -----------------

View File

@ -340,6 +340,35 @@ Default: ``'csrftoken'``
The name of the cookie to use for the CSRF authentication token. This can be whatever you The name of the cookie to use for the CSRF authentication token. This can be whatever you
want. See :doc:`/ref/contrib/csrf`. want. See :doc:`/ref/contrib/csrf`.
.. setting:: CSRF_COOKIE_PATH
CSRF_COOKIE_PATH
----------------
.. versionadded:: 1.4
Default: ``'/'``
The path set on the CSRF cookie. This should either match the URL path of your
Django installation or be a parent of that path.
This is useful if you have multiple Django instances running under the same
hostname. They can use different cookie paths, and each instance will only see
its own CSRF cookie.
.. setting:: CSRF_COOKIE_SECURE
CSRF_COOKIE_SECURE
------------------
.. versionadded:: 1.4
Default: ``False``
Whether to use a secure cookie for the CSRF 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:: CSRF_FAILURE_VIEW .. setting:: CSRF_FAILURE_VIEW
CSRF_FAILURE_VIEW CSRF_FAILURE_VIEW

View File

@ -82,13 +82,21 @@ class CsrfViewMiddlewareTest(TestCase):
patched. patched.
""" """
req = self._get_GET_no_csrf_cookie_request() req = self._get_GET_no_csrf_cookie_request()
# Put tests for CSRF_COOKIE_* settings here
with self.settings(CSRF_COOKIE_NAME='myname',
CSRF_COOKIE_DOMAIN='.example.com',
CSRF_COOKIE_PATH='/test/',
CSRF_COOKIE_SECURE=True):
# token_view calls get_token() indirectly # token_view calls get_token() indirectly
CsrfViewMiddleware().process_view(req, token_view, (), {}) CsrfViewMiddleware().process_view(req, token_view, (), {})
resp = token_view(req) resp = token_view(req)
resp2 = CsrfViewMiddleware().process_response(req, resp) resp2 = CsrfViewMiddleware().process_response(req, resp)
csrf_cookie = resp2.cookies.get('myname', False)
csrf_cookie = resp2.cookies.get(settings.CSRF_COOKIE_NAME, False)
self.assertNotEqual(csrf_cookie, False) self.assertNotEqual(csrf_cookie, False)
self.assertEqual(csrf_cookie['domain'], '.example.com')
self.assertEqual(csrf_cookie['secure'], True)
self.assertEqual(csrf_cookie['path'], '/test/')
self.assertTrue('Cookie' in resp2.get('Vary','')) self.assertTrue('Cookie' in resp2.get('Vary',''))
def test_process_response_get_token_not_used(self): def test_process_response_get_token_not_used(self):