diff --git a/django/contrib/csrf/middleware.py b/django/contrib/csrf/middleware.py index dee6f4f429..f6f78867dc 100644 --- a/django/contrib/csrf/middleware.py +++ b/django/contrib/csrf/middleware.py @@ -9,6 +9,7 @@ from django.conf import settings from django.http import HttpResponseForbidden import md5 import re +import itertools _ERROR_MSG = "

403 Forbidden

Cross Site Request Forgery detected. Request aborted.

" @@ -19,7 +20,7 @@ _HTML_TYPES = ('text/html', 'application/xhtml+xml') def _make_token(session_id): return md5.new(settings.SECRET_KEY + session_id).hexdigest() - + class CsrfMiddleware(object): """Django middleware that adds protection against Cross Site Request Forgeries by adding hidden form fields to POST forms and @@ -57,7 +58,7 @@ class CsrfMiddleware(object): return HttpResponseForbidden(_ERROR_MSG) return None - + def process_response(self, request, response): csrf_token = None try: @@ -74,11 +75,18 @@ class CsrfMiddleware(object): pass if csrf_token is not None and \ - response['Content-Type'].split(';')[0] in _HTML_TYPES: - + response['Content-Type'].split(';')[0] in _HTML_TYPES: + + # ensure we don't add the 'id' attribute twice (HTML validity) + idattributes = itertools.chain(("id='csrfmiddlewaretoken'",), + itertools.repeat('')) + def add_csrf_field(match): + """Returns the matched
tag plus the added element""" + return match.group() + "
" + \ + "
" + # Modify any POST forms - extra_field = "
" + \ - "
" - response.content = _POST_FORM_RE.sub('\\1' + extra_field, response.content) + response.content = _POST_FORM_RE.sub(add_csrf_field, response.content) return response