Ticket #9172: 9172_r9084.diff

File 9172_r9084.diff, 5.3 KB (added by Carl Meyer, 16 years ago)

make test client bypass CsrfMiddleware

  • django/test/client.py

     
    1818from django.utils.encoding import smart_str
    1919from django.utils.http import urlencode
    2020from django.utils.itercompat import is_iterable
     21from django.contrib.csrf.middleware import CSRF_TOKEN_NAME, _make_token
    2122
    2223BOUNDARY = 'BoUnDaRyStRiNg'
    2324MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
     
    268269        """
    269270        Requests a response from the server using POST.
    270271        """
     272        if ('django.contrib.csrf.middleware.CsrfMiddleware' in
     273            settings.MIDDLEWARE_CLASSES and
     274            hasattr(self.session, 'session_key')):
     275            data[CSRF_TOKEN_NAME] = _make_token(self.session.session_key)
     276           
    271277        if content_type is MULTIPART_CONTENT:
    272278            post_data = encode_multipart(BOUNDARY, data)
    273279        else:
  • django/contrib/csrf/middleware.py

     
    1313from django.utils.hashcompat import md5_constructor
    1414from django.utils.safestring import mark_safe
    1515
     16CSRF_TOKEN_NAME = 'csrfmiddlewaretoken'
     17
    1618_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>')
    1719
    1820_POST_FORM_RE = \
     
    5254            csrf_token = _make_token(session_id)
    5355            # check incoming token
    5456            try:
    55                 request_csrf_token = request.POST['csrfmiddlewaretoken']
     57                request_csrf_token = request.POST[CSRF_TOKEN_NAME]
    5658            except KeyError:
    5759                return HttpResponseForbidden(_ERROR_MSG)
    5860
     
    8082                response['Content-Type'].split(';')[0] in _HTML_TYPES:
    8183
    8284            # ensure we don't add the 'id' attribute twice (HTML validity)
    83             idattributes = itertools.chain(("id='csrfmiddlewaretoken'",),
     85            idattributes = itertools.chain(("id='%s'" % (CSRF_TOKEN_NAME,),),
    8486                                            itertools.repeat(''))
    8587            def add_csrf_field(match):
    8688                """Returns the matched <form> tag plus the added <input> element"""
    8789                return mark_safe(match.group() + "<div style='display:none;'>" + \
    8890                "<input type='hidden' " + idattributes.next() + \
    89                 " name='csrfmiddlewaretoken' value='" + csrf_token + \
     91                " name='" + CSRF_TOKEN_NAME + "' value='" + csrf_token + \
    9092                "' /></div>")
    9193
    9294            # Modify any POST forms
  • tests/regressiontests/test_client_regress/models.py

     
    382382        response = self.client.get('/test_client_regress/check_session/')
    383383        self.assertEqual(response.status_code, 200)
    384384        self.assertEqual(response.content, 'YES')
    385        
    386  No newline at end of file
     385
     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)
  • docs/ref/contrib/csrf.txt

     
    7373you might bypass the filter that adds the hidden field to the form,
    7474in which case form submission will always fail.  It may still be possible
    7575to use the middleware, provided you can find some way to get the
    76 CSRF token and ensure that is included when your form is submitted.
    77  No newline at end of file
     76CSRF token and ensure that is included when your form is submitted.
     77
     78Testing
     79=======
     80
     81The :mod:`Django test client <django.test.client>` automatically
     82bypasses CsrfMiddleware, for easier testing of POST requests.
Back to Top