diff -r 57b4279d8c4e -r 03e267d67478 app/django/contrib/csrf/middleware.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/django/contrib/csrf/middleware.py Fri Jul 18 18:22:23 2008 +0000 @@ -0,0 +1,93 @@ +""" +Cross Site Request Forgery Middleware. + +This module provides a middleware that implements protection +against request forgeries from other sites. + +""" +from django.conf import settings +from django.http import HttpResponseForbidden +from django.utils.safestring import mark_safe +import md5 +import re +import itertools + +_ERROR_MSG = mark_safe('

403 Forbidden

Cross Site Request Forgery detected. Request aborted.

') + +_POST_FORM_RE = \ + re.compile(r'(]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE) + +_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 + checking requests for the correct value. + + In the list of middlewares, SessionMiddleware is required, and must come + after this middleware. CsrfMiddleWare must come after compression + middleware. + + If a session ID cookie is present, it is hashed with the SECRET_KEY + setting to create an authentication token. This token is added to all + outgoing POST forms and is expected on all incoming POST requests that + have a session ID cookie. + + If you are setting cookies directly, instead of using Django's session + framework, this middleware will not work. + """ + + def process_request(self, request): + if request.method == 'POST': + try: + session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] + except KeyError: + # No session, no check required + return None + + csrf_token = _make_token(session_id) + # check incoming token + try: + request_csrf_token = request.POST['csrfmiddlewaretoken'] + except KeyError: + return HttpResponseForbidden(_ERROR_MSG) + + if request_csrf_token != csrf_token: + return HttpResponseForbidden(_ERROR_MSG) + + return None + + def process_response(self, request, response): + csrf_token = None + try: + cookie = response.cookies[settings.SESSION_COOKIE_NAME] + csrf_token = _make_token(cookie.value) + except KeyError: + # No outgoing cookie to set session, but + # a session might already exist. + try: + session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] + csrf_token = _make_token(session_id) + except KeyError: + # no incoming or outgoing cookie + pass + + if csrf_token is not None and \ + 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 mark_safe(match.group() + "
" + \ + "
") + + # Modify any POST forms + response.content = _POST_FORM_RE.sub(add_csrf_field, response.content) + return response