Fixed #21322 -- Error message when CSRF cookie is missing

Thanks to Henrik Levkowetz and olau for their reports and initial patches.
This commit is contained in:
Bouke Haarsma 2013-11-03 09:18:48 +01:00 committed by Claude Paroz
parent f67e18f39e
commit 9b95fa7777
2 changed files with 50 additions and 4 deletions

View File

@ -41,6 +41,10 @@ CSRF_FAILURE_TEMPLATE = """
<p>{{ no_referer1 }}</p> <p>{{ no_referer1 }}</p>
<p>{{ no_referer2 }}</p> <p>{{ no_referer2 }}</p>
{% endif %} {% endif %}
{% if no_cookie %}
<p>{{ no_cookie1 }}</p>
<p>{{ no_cookie2 }}</p>
{% endif %}
</div> </div>
{% if DEBUG %} {% if DEBUG %}
<div id="info"> <div id="info">
@ -95,7 +99,7 @@ def csrf_failure(request, reason=""):
""" """
Default view used when request fails CSRF protection Default view used when request fails CSRF protection
""" """
from django.middleware.csrf import REASON_NO_REFERER from django.middleware.csrf import REASON_NO_REFERER, REASON_NO_CSRF_COOKIE
t = Template(CSRF_FAILURE_TEMPLATE) t = Template(CSRF_FAILURE_TEMPLATE)
c = Context({ c = Context({
'title': _("Forbidden"), 'title': _("Forbidden"),
@ -111,6 +115,16 @@ def csrf_failure(request, reason=""):
"If you have configured your browser to disable 'Referer' headers, " "If you have configured your browser to disable 'Referer' headers, "
"please re-enable them, at least for this site, or for HTTPS " "please re-enable them, at least for this site, or for HTTPS "
"connections, or for 'same-origin' requests."), "connections, or for 'same-origin' requests."),
'no_cookie': reason == REASON_NO_CSRF_COOKIE,
'no_cookie1': _(
"You are seeing this message because this site requires a CSRF "
"cookie when submitting forms. This cookie is required for "
"security reasons, to ensure that your browser is not being "
"hijacked by third parties."),
'no_cookie2': _(
"If you have configured your browser to disable cookies, please "
"re-enable them, at least for this site, or for 'same-origin' "
"requests."),
'DEBUG': settings.DEBUG, 'DEBUG': settings.DEBUG,
'more': _("More information is available with DEBUG=True."), 'more': _("More information is available with DEBUG=True."),
}) })

View File

@ -5,6 +5,10 @@ from django.utils.translation import override
class CsrfViewTests(TestCase): class CsrfViewTests(TestCase):
urls = "view_tests.urls" urls = "view_tests.urls"
def setUp(self):
super(CsrfViewTests, self).setUp()
self.client = Client(enforce_csrf_checks=True)
@override_settings( @override_settings(
USE_I18N=True, USE_I18N=True,
MIDDLEWARE_CLASSES=( MIDDLEWARE_CLASSES=(
@ -17,17 +21,45 @@ class CsrfViewTests(TestCase):
""" """
Test that an invalid request is rejected with a localized error message. Test that an invalid request is rejected with a localized error message.
""" """
self.client = Client(enforce_csrf_checks=True)
response = self.client.post('/', HTTP_HOST='www.example.com') response = self.client.post('/')
self.assertContains(response, "Forbidden", status_code=403) self.assertContains(response, "Forbidden", status_code=403)
self.assertContains(response, self.assertContains(response,
"CSRF verification failed. Request aborted.", "CSRF verification failed. Request aborted.",
status_code=403) status_code=403)
with self.settings(LANGUAGE_CODE='nl'), override('en-us'): with self.settings(LANGUAGE_CODE='nl'), override('en-us'):
response = self.client.post('/', HTTP_HOST='www.example.com') response = self.client.post('/')
self.assertContains(response, "Verboden", status_code=403) self.assertContains(response, "Verboden", status_code=403)
self.assertContains(response, self.assertContains(response,
"CSRF-verificatie mislukt. Verzoek afgebroken.", "CSRF-verificatie mislukt. Verzoek afgebroken.",
status_code=403) status_code=403)
@override_settings(
SECURE_PROXY_SSL_HEADER=('HTTP_X_FORWARDED_PROTO', 'https')
)
def test_no_referer(self):
"""
Referer header is strictly checked for POST over HTTPS. Trigger the
exception by sending an incorrect referer.
"""
response = self.client.post('/', HTTP_X_FORWARDED_PROTO='https')
self.assertContains(response,
"You are seeing this message because this HTTPS "
"site requires a &#39;Referer header&#39; to be "
"sent by your Web browser, but none was sent.",
status_code=403)
def test_no_cookies(self):
"""
The CSRF cookie is checked for POST. Failure to send this cookie should
provide a nice error message.
"""
response = self.client.post('/')
self.assertContains(response,
"You are seeing this message because this site "
"requires a CSRF cookie when submitting forms. "
"This cookie is required for security reasons, to "
"ensure that your browser is not being hijacked "
"by third parties.",
status_code=403)