Fixed #20128 -- Made CsrfViewMiddleware ignore IOError when reading POST data.

Thanks Walter Doekes.
This commit is contained in:
Tim Graham 2014-06-25 06:52:25 -04:00
parent fd4ccd045c
commit 815e7a5721
2 changed files with 50 additions and 1 deletions

View File

@ -167,7 +167,15 @@ class CsrfViewMiddleware(object):
# Check non-cookie token for match. # Check non-cookie token for match.
request_csrf_token = "" request_csrf_token = ""
if request.method == "POST": if request.method == "POST":
try:
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '') request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
except IOError:
# Handle a broken connection before we've completed reading
# the POST data. process_view shouldn't raise any
# exceptions, so we'll ignore and serve the user a 403
# (assuming they're still listening, which they probably
# aren't because of the error).
pass
if request_csrf_token == "": if request_csrf_token == "":
# Fall back to X-CSRFToken, to make things easier for AJAX, # Fall back to X-CSRFToken, to make things easier for AJAX,

View File

@ -428,3 +428,44 @@ class CsrfViewMiddlewareTest(TestCase):
resp2 = CsrfViewMiddleware().process_response(req, resp) resp2 = CsrfViewMiddleware().process_response(req, resp)
max_age = resp2.cookies.get('csrfcookie').get('max-age') max_age = resp2.cookies.get('csrfcookie').get('max-age')
self.assertEqual(max_age, '') self.assertEqual(max_age, '')
def test_post_data_read_failure(self):
"""
#20128 -- IOErrors during POST data reading should be caught and
treated as if the POST data wasn't there.
"""
class CsrfPostRequest(HttpRequest):
"""
HttpRequest that can raise an IOError when accessing POST data
"""
def __init__(self, token, raise_error):
super(CsrfPostRequest, self).__init__()
self.method = 'POST'
self.raise_error = False
self.COOKIES[settings.CSRF_COOKIE_NAME] = token
self.POST['csrfmiddlewaretoken'] = token
self.raise_error = raise_error
def _load_post_and_files(self):
raise IOError('error reading input data')
def _get_post(self):
if self.raise_error:
self._load_post_and_files()
return self._post
def _set_post(self, post):
self._post = post
POST = property(_get_post, _set_post)
token = 'ABC'
req = CsrfPostRequest(token, raise_error=False)
resp = CsrfViewMiddleware().process_view(req, post_form_view, (), {})
self.assertEqual(resp, None)
req = CsrfPostRequest(token, raise_error=True)
resp = CsrfViewMiddleware().process_view(req, post_form_view, (), {})
self.assertEqual(resp.status_code, 403)