Fixed #22185 -- Added settings.CSRF_COOKIE_AGE

Thanks Paul McMillan for the review.
This commit is contained in:
Roger Hu 2014-03-04 00:52:28 +00:00 committed by Tim Graham
parent 06efeae598
commit 9b729ddd8f
6 changed files with 75 additions and 1 deletions

View File

@ -558,6 +558,7 @@ CSRF_FAILURE_VIEW = 'django.views.csrf.csrf_failure'
# Settings for CSRF cookie. # Settings for CSRF cookie.
CSRF_COOKIE_NAME = 'csrftoken' CSRF_COOKIE_NAME = 'csrftoken'
CSRF_COOKIE_AGE = 60 * 60 * 24 * 7 * 52
CSRF_COOKIE_DOMAIN = None CSRF_COOKIE_DOMAIN = None
CSRF_COOKIE_PATH = '/' CSRF_COOKIE_PATH = '/'
CSRF_COOKIE_SECURE = False CSRF_COOKIE_SECURE = False

View File

@ -196,7 +196,7 @@ class CsrfViewMiddleware(object):
# the expiry timer. # the expiry timer.
response.set_cookie(settings.CSRF_COOKIE_NAME, response.set_cookie(settings.CSRF_COOKIE_NAME,
request.META["CSRF_COOKIE"], request.META["CSRF_COOKIE"],
max_age=60 * 60 * 24 * 7 * 52, max_age=settings.CSRF_COOKIE_AGE,
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,

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_AGE`
* :setting:`CSRF_COOKIE_DOMAIN` * :setting:`CSRF_COOKIE_DOMAIN`
* :setting:`CSRF_COOKIE_HTTPONLY` * :setting:`CSRF_COOKIE_HTTPONLY`
* :setting:`CSRF_COOKIE_NAME` * :setting:`CSRF_COOKIE_NAME`

View File

@ -324,6 +324,28 @@ See :doc:`/topics/cache`.
.. _settings-csrf: .. _settings-csrf:
.. setting:: CSRF_COOKIE_AGE
CSRF_COOKIE_AGE
---------------
.. versionadded:: 1.7
Default: ``31449600`` (1 year, in seconds)
The age of CSRF cookies, in seconds.
The reason for setting a long-lived expiration time is to avoid problems in
the case of a user closing a browser or bookmarking a page and then loading
that page from a browser cache. Without persistent cookies, the form submission
would fail in this case.
Some browsers (specifically Internet Explorer) can disallow the use of
persistent cookies or can have the indexes to the cookie jar corrupted on disk,
thereby causing CSRF protection checks to fail (and sometimes intermittently).
Change this setting to ``None`` to use session-based CSRF cookies, which
keep the cookies in-memory instead of on persistent storage.
.. setting:: CSRF_COOKIE_DOMAIN .. setting:: CSRF_COOKIE_DOMAIN
CSRF_COOKIE_DOMAIN CSRF_COOKIE_DOMAIN

View File

@ -446,6 +446,12 @@ Cache
"non-expiring" by default. Previously, it was only possible to pass "non-expiring" by default. Previously, it was only possible to pass
``timeout=None` to the cache backend's ``set()`` method. ``timeout=None` to the cache backend's ``set()`` method.
Cross Site Request Forgery
^^^^^^^^^^^^^^^^^^^^^^^^^^
* The :setting:`CSRF_COOKIE_AGE` setting facilitates the use of session-based
CSRF cookies.
Email Email
^^^^^ ^^^^^

View File

@ -384,3 +384,47 @@ class CsrfViewMiddlewareTest(TestCase):
finally: finally:
logger.removeHandler(test_handler) logger.removeHandler(test_handler)
logger.setLevel(old_log_level) logger.setLevel(old_log_level)
def test_csrf_cookie_age(self):
"""
Test to verify CSRF cookie age can be set using
settings.CSRF_COOKIE_AGE.
"""
req = self._get_GET_no_csrf_cookie_request()
MAX_AGE = 123
with self.settings(CSRF_COOKIE_NAME='csrfcookie',
CSRF_COOKIE_DOMAIN='.example.com',
CSRF_COOKIE_AGE=MAX_AGE,
CSRF_COOKIE_PATH='/test/',
CSRF_COOKIE_SECURE=True,
CSRF_COOKIE_HTTPONLY=True):
# token_view calls get_token() indirectly
CsrfViewMiddleware().process_view(req, token_view, (), {})
resp = token_view(req)
resp2 = CsrfViewMiddleware().process_response(req, resp)
max_age = resp2.cookies.get('csrfcookie').get('max-age')
self.assertEqual(max_age, MAX_AGE)
def test_csrf_cookie_age_none(self):
"""
Test to verify CSRF cookie age does not have max age set and therefore
uses session-based cookies.
"""
req = self._get_GET_no_csrf_cookie_request()
MAX_AGE = None
with self.settings(CSRF_COOKIE_NAME='csrfcookie',
CSRF_COOKIE_DOMAIN='.example.com',
CSRF_COOKIE_AGE=MAX_AGE,
CSRF_COOKIE_PATH='/test/',
CSRF_COOKIE_SECURE=True,
CSRF_COOKIE_HTTPONLY=True):
# token_view calls get_token() indirectly
CsrfViewMiddleware().process_view(req, token_view, (), {})
resp = token_view(req)
resp2 = CsrfViewMiddleware().process_response(req, resp)
max_age = resp2.cookies.get('csrfcookie').get('max-age')
self.assertEqual(max_age, '')