Ticket #9172: django-trunk-csrf-test-client.patch

File django-trunk-csrf-test-client.patch, 5.1 KB (added by Markus Bertheau, 15 years ago)

Updated patch for current trunk

  • django/test/client.py

     
    1919from django.utils.encoding import smart_str
    2020from django.utils.http import urlencode
    2121from django.utils.itercompat import is_iterable
     22from django.contrib.csrf.middleware import CSRF_TOKEN_NAME, _make_token
    2223from django.db import transaction, close_connection
    2324
    2425BOUNDARY = 'BoUnDaRyStRiNg'
     
    280281        """
    281282        Requests a response from the server using POST.
    282283        """
     284        if ('django.contrib.csrf.middleware.CsrfMiddleware' in
     285            settings.MIDDLEWARE_CLASSES and
     286            hasattr(self.session, 'session_key')):
     287            data[CSRF_TOKEN_NAME] = _make_token(self.session.session_key)
     288           
    283289        if content_type is MULTIPART_CONTENT:
    284290            post_data = encode_multipart(BOUNDARY, data)
    285291        else:
  • django/contrib/csrf/middleware.py

     
    1717from django.utils.hashcompat import md5_constructor
    1818from django.utils.safestring import mark_safe
    1919
     20CSRF_TOKEN_NAME = 'csrfmiddlewaretoken'
     21
    2022_ERROR_MSG = mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>Cross Site Request Forgery detected. Request aborted.</p></body></html>')
    2123
    2224_POST_FORM_RE = \
     
    4951            csrf_token = _make_token(session_id)
    5052            # check incoming token
    5153            try:
    52                 request_csrf_token = request.POST['csrfmiddlewaretoken']
     54                request_csrf_token = request.POST[CSRF_TOKEN_NAME]
    5355            except KeyError:
    5456                return HttpResponseForbidden(_ERROR_MSG)
    5557
     
    8890                response['Content-Type'].split(';')[0] in _HTML_TYPES:
    8991
    9092            # ensure we don't add the 'id' attribute twice (HTML validity)
    91             idattributes = itertools.chain(("id='csrfmiddlewaretoken'",),
     93            idattributes = itertools.chain(("id='%s'" % (CSRF_TOKEN_NAME,),),
    9294                                            itertools.repeat(''))
    9395            def add_csrf_field(match):
    9496                """Returns the matched <form> tag plus the added <input> element"""
    9597                return mark_safe(match.group() + "<div style='display:none;'>" + \
    9698                "<input type='hidden' " + idattributes.next() + \
    97                 " name='csrfmiddlewaretoken' value='" + csrf_token + \
     99                " name='" + CSRF_TOKEN_NAME + "' value='" + csrf_token + \
    98100                "' /></div>")
    99101
    100102            # Modify any POST forms
  • tests/regressiontests/test_client_regress/models.py

     
    383383        self.assertEqual(response.status_code, 200)
    384384        self.assertEqual(response.content, 'YES')
    385385
     386class CsrfMiddlewareAvoidanceTests(TestCase):
     387    fixtures = ['testdata.json']
     388
     389    def setUp(self):
     390        self.old_middleware_classes = settings.MIDDLEWARE_CLASSES
     391        settings.MIDDLEWARE_CLASSES = (
     392            'django.contrib.csrf.middleware.CsrfMiddleware',
     393            'django.contrib.sessions.middleware.SessionMiddleware',
     394            'django.contrib.auth.middleware.AuthenticationMiddleware',
     395            'django.middleware.common.CommonMiddleware',
     396            )
     397
     398    def tearDown(self):
     399        settings.MIDDLEWARE_CLASSES = self.old_middleware_classes
     400
     401    def test_circumvent_csrf_middleware(self):
     402        # Csrf middleware only activates if there is a session
     403        login = self.client.login(username='testclient',password='password')
     404        self.failUnless(login, 'Could not log in')
     405
     406        response = self.client.post('/test_client_regress/no_template_view/',
     407                                    {'some': 'post data'})
     408
     409        # if we'd gotten caught by CsrfMiddleware, we'd get a 403
     410        self.assertEqual(response.status_code, 200)
     411        self.client.logout()
     412
     413    def test_logged_out_post_still_works(self):
     414        response = self.client.post('/test_client_regress/no_template_view/',
     415                                    {'some': 'post data'})
     416        self.assertEqual(response.status_code, 200)
     417
    386418class RequestMethodTests(TestCase):
    387419    def test_get(self):
    388420        "Request a view via request method GET"
  • docs/ref/contrib/csrf.txt

     
    111111in which case form submission will always fail.  It may still be possible
    112112to use the middleware, provided you can find some way to get the
    113113CSRF token and ensure that is included when your form is submitted.
     114
     115Testing
     116=======
     117
     118The :mod:`Django test client <django.test.client>` automatically
     119bypasses CsrfMiddleware, for easier testing of POST requests.
Back to Top