瀏覽代碼

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

Thanks to Henrik Levkowetz and olau for their reports and initial patches.
Bouke Haarsma 11 年之前
父節點
當前提交
9b95fa7777
共有 2 個文件被更改,包括 50 次插入4 次删除
  1. 15 1
      django/views/csrf.py
  2. 35 3
      tests/view_tests/tests/test_csrf.py

+ 15 - 1
django/views/csrf.py

@@ -41,6 +41,10 @@ CSRF_FAILURE_TEMPLATE = """
   <p>{{ no_referer1 }}</p>
   <p>{{ no_referer2 }}</p>
 {% endif %}
+{% if no_cookie %}
+  <p>{{ no_cookie1 }}</p>
+  <p>{{ no_cookie2 }}</p>
+{% endif %}
 </div>
 {% if DEBUG %}
 <div id="info">
@@ -95,7 +99,7 @@ def csrf_failure(request, reason=""):
     """
     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)
     c = Context({
         'title': _("Forbidden"),
@@ -111,6 +115,16 @@ def csrf_failure(request, reason=""):
             "If you have configured your browser to disable 'Referer' headers, "
             "please re-enable them, at least for this site, or for HTTPS "
             "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,
         'more': _("More information is available with DEBUG=True."),
     })

+ 35 - 3
tests/view_tests/tests/test_csrf.py

@@ -5,6 +5,10 @@ from django.utils.translation import override
 class CsrfViewTests(TestCase):
     urls = "view_tests.urls"
 
+    def setUp(self):
+        super(CsrfViewTests, self).setUp()
+        self.client = Client(enforce_csrf_checks=True)
+
     @override_settings(
         USE_I18N=True,
         MIDDLEWARE_CLASSES=(
@@ -17,17 +21,45 @@ class CsrfViewTests(TestCase):
         """
         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,
                             "CSRF verification failed. Request aborted.",
                             status_code=403)
 
         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,
                                 "CSRF-verificatie mislukt. Verzoek afgebroken.",
                                 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)