summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorLuke Plant <L.Plant.98@cantab.net>2009-02-07 17:47:02 +0000
committerLuke Plant <L.Plant.98@cantab.net>2009-02-07 17:47:02 +0000
commit9a2e33810789017dfb2cbe46afa01f3f45357757 (patch)
treebdee6580501a70f017d13183bf207a309f691e90 /django
parentfffade663365ee50f32a0c3b05915fba15a5fe3b (diff)
Made CSRF middleware skip post-processing for 'csrf_exempt' decorated views.
This commit also decomposes the decorator into two decorators which can be used separately, adds some tests, updates docs and fixes some code comments. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9815 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
-rw-r--r--django/contrib/csrf/middleware.py35
-rw-r--r--django/contrib/csrf/tests.py18
2 files changed, 44 insertions, 9 deletions
diff --git a/django/contrib/csrf/middleware.py b/django/contrib/csrf/middleware.py
index 3a06feb398..30cb8caa5e 100644
--- a/django/contrib/csrf/middleware.py
+++ b/django/contrib/csrf/middleware.py
@@ -65,9 +65,12 @@ class CsrfResponseMiddleware(object):
session.
"""
def process_response(self, request, response):
+ if getattr(response, 'csrf_exempt', False):
+ return response
+
csrf_token = None
try:
- # This covers a corner case in which the outgoing request
+ # This covers a corner case in which the outgoing response
# both contains a form and sets a session cookie. This
# really should not be needed, since it is best if views
# that create a new session (login pages) also do a
@@ -123,13 +126,35 @@ class CsrfMiddleware(CsrfViewMiddleware, CsrfResponseMiddleware):
"""
pass
-def csrf_exempt(view_func):
+def csrf_response_exempt(view_func):
"""
- Marks a view function as being exempt from the CSRF checks
+ Modifies a view function so that its response is exempt
+ from the post-processing of the CSRF middleware.
+ """
+ def wrapped_view(*args, **kwargs):
+ resp = view_func(*args, **kwargs)
+ resp.csrf_exempt = True
+ return resp
+ return wraps(view_func)(wrapped_view)
+
+def csrf_view_exempt(view_func):
"""
+ Marks a view function as being exempt from CSRF view protection.
+ """
+ # We could just do view_func.csrf_exempt = True, but decorators
+ # are nicer if they don't have side-effects, so we return a new
+ # function.
def wrapped_view(*args, **kwargs):
return view_func(*args, **kwargs)
- # We could just do view.csrf_exempt = True, but decorators are
- # nicer if they don't have side-effects.
wrapped_view.csrf_exempt = True
return wraps(view_func)(wrapped_view)
+
+def csrf_exempt(view_func):
+ """
+ Marks a view function as being exempt from the CSRF checks
+ and post processing.
+
+ This is the same as using both the csrf_exempt_view and
+ csrf_exempt_response decorators.
+ """
+ return csrf_response_exempt(csrf_view_exempt(view_func))
diff --git a/django/contrib/csrf/tests.py b/django/contrib/csrf/tests.py
index b9f402e1a9..ba934bc7ea 100644
--- a/django/contrib/csrf/tests.py
+++ b/django/contrib/csrf/tests.py
@@ -63,7 +63,7 @@ class CsrfMiddlewareTest(TestCase):
"""
req = self._get_GET_no_session_request()
resp = self._get_post_form_response()
- resp_content = resp.content
+ resp_content = resp.content # needed because process_response modifies resp
resp2 = CsrfMiddleware().process_response(req, resp)
self.assertEquals(resp_content, resp2.content)
@@ -73,7 +73,7 @@ class CsrfMiddlewareTest(TestCase):
"""
req = self._get_GET_session_request()
resp = self._get_post_form_response()
- resp_content = resp.content
+ resp_content = resp.content # needed because process_response modifies resp
resp2 = CsrfMiddleware().process_response(req, resp)
self.assertNotEqual(resp_content, resp2.content)
self._check_token_present(resp2)
@@ -84,11 +84,21 @@ class CsrfMiddlewareTest(TestCase):
"""
req = self._get_GET_no_session_request() # no session in request
resp = self._get_new_session_response() # but new session started
- resp_content = resp.content
+ resp_content = resp.content # needed because process_response modifies resp
resp2 = CsrfMiddleware().process_response(req, resp)
self.assertNotEqual(resp_content, resp2.content)
self._check_token_present(resp2)
+ def test_process_response_exempt_view(self):
+ """
+ Check that no post processing is done for an exempt view
+ """
+ req = self._get_POST_session_request()
+ resp = csrf_exempt(self.get_view())(req)
+ resp_content = resp.content
+ resp2 = CsrfMiddleware().process_response(req, resp)
+ self.assertEquals(resp_content, resp2.content)
+
# Check the request processing
def test_process_request_no_session(self):
"""
@@ -126,7 +136,7 @@ class CsrfMiddlewareTest(TestCase):
def test_ajax_exemption(self):
"""
- Check the AJAX requests are automatically exempted.
+ Check that AJAX requests are automatically exempted.
"""
req = self._get_POST_session_request()
req.META['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'