Fixed #15808 -- Added optional HttpOnly flag to the CSRF Cookie.

Thanks Samuel Lavitt for the report and Sascha Peilicke for the patch.
This commit is contained in:
Aymeric Augustin 2013-02-07 09:48:08 +01:00
parent 6afc85af47
commit 720888a146
6 changed files with 23 additions and 2 deletions

View File

@ -529,6 +529,7 @@ CSRF_COOKIE_NAME = 'csrftoken'
CSRF_COOKIE_DOMAIN = None CSRF_COOKIE_DOMAIN = None
CSRF_COOKIE_PATH = '/' CSRF_COOKIE_PATH = '/'
CSRF_COOKIE_SECURE = False CSRF_COOKIE_SECURE = False
CSRF_COOKIE_HTTPONLY = False
############ ############
# MESSAGES # # MESSAGES #

View File

@ -210,7 +210,8 @@ class CsrfViewMiddleware(object):
max_age = 60 * 60 * 24 * 7 * 52, max_age = 60 * 60 * 24 * 7 * 52,
domain=settings.CSRF_COOKIE_DOMAIN, domain=settings.CSRF_COOKIE_DOMAIN,
path=settings.CSRF_COOKIE_PATH, path=settings.CSRF_COOKIE_PATH,
secure=settings.CSRF_COOKIE_SECURE secure=settings.CSRF_COOKIE_SECURE,
httponly=settings.CSRF_COOKIE_HTTPONLY
) )
# 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',))

View File

@ -491,6 +491,7 @@ Settings
A number of settings can be used to control Django's CSRF behavior: A number of settings can be used to control Django's CSRF behavior:
* :setting:`CSRF_COOKIE_DOMAIN` * :setting:`CSRF_COOKIE_DOMAIN`
* :setting:`CSRF_COOKIE_HTTPONLY`
* :setting:`CSRF_COOKIE_NAME` * :setting:`CSRF_COOKIE_NAME`
* :setting:`CSRF_COOKIE_PATH` * :setting:`CSRF_COOKIE_PATH`
* :setting:`CSRF_COOKIE_SECURE` * :setting:`CSRF_COOKIE_SECURE`

View File

@ -281,6 +281,19 @@ Please note that the presence of this setting does not imply that Django's CSRF
protection is safe from cross-subdomain attacks by default - please see the protection is safe from cross-subdomain attacks by default - please see the
:ref:`CSRF limitations <csrf-limitations>` section. :ref:`CSRF limitations <csrf-limitations>` section.
.. setting:: CSRF_COOKIE_HTTPONLY
CSRF_COOKIE_HTTPONLY
--------------------
.. versionadded:: 1.6
Default: ``False``
Whether to use HttpOnly flag on the CSRF cookie. If this is set to ``True``,
client-side JavaScript will not to be able to access the CSRF cookie. See
:setting:`SESSION_COOKIE_HTTPONLY` for details on HttpOnly.
.. setting:: CSRF_COOKIE_NAME .. setting:: CSRF_COOKIE_NAME
CSRF_COOKIE_NAME CSRF_COOKIE_NAME

View File

@ -36,6 +36,9 @@ Minor features
* Authentication backends can raise ``PermissionDenied`` to immediately fail * Authentication backends can raise ``PermissionDenied`` to immediately fail
the authentication chain. the authentication chain.
* The HttpOnly flag can be set on the CSRF cookie with
:setting:`CSRF_COOKIE_HTTPONLY`.
* The ``assertQuerysetEqual()`` now checks for undefined order and raises * The ``assertQuerysetEqual()`` now checks for undefined order and raises
``ValueError`` if undefined order is spotted. The order is seen as ``ValueError`` if undefined order is spotted. The order is seen as
undefined if the given ``QuerySet`` isn't ordered and there are more than undefined if the given ``QuerySet`` isn't ordered and there are more than

View File

@ -101,7 +101,8 @@ class CsrfViewMiddlewareTest(TestCase):
with self.settings(CSRF_COOKIE_NAME='myname', with self.settings(CSRF_COOKIE_NAME='myname',
CSRF_COOKIE_DOMAIN='.example.com', CSRF_COOKIE_DOMAIN='.example.com',
CSRF_COOKIE_PATH='/test/', CSRF_COOKIE_PATH='/test/',
CSRF_COOKIE_SECURE=True): CSRF_COOKIE_SECURE=True,
CSRF_COOKIE_HTTPONLY=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)
@ -110,6 +111,7 @@ class CsrfViewMiddlewareTest(TestCase):
self.assertNotEqual(csrf_cookie, False) self.assertNotEqual(csrf_cookie, False)
self.assertEqual(csrf_cookie['domain'], '.example.com') self.assertEqual(csrf_cookie['domain'], '.example.com')
self.assertEqual(csrf_cookie['secure'], True) self.assertEqual(csrf_cookie['secure'], True)
self.assertEqual(csrf_cookie['httponly'], True)
self.assertEqual(csrf_cookie['path'], '/test/') self.assertEqual(csrf_cookie['path'], '/test/')
self.assertTrue('Cookie' in resp2.get('Vary','')) self.assertTrue('Cookie' in resp2.get('Vary',''))