Commit c0f9e85f authored by Luke Plant's avatar Luke Plant
Browse files

Split CsrfMiddleware into two to make it more reusable.

Also converted it to be a view middleware instead of request,
as this allows more options.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@9553 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 01ec6d00
Loading
Loading
Loading
Loading
+33 −18
Original line number Diff line number Diff line
@@ -23,25 +23,12 @@ _HTML_TYPES = ('text/html', 'application/xhtml+xml')
def _make_token(session_id):
    return md5_constructor(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.
class CsrfViewMiddleware(object):
    """

    def process_request(self, request):
    Middleware that requires a present and correct csrfmiddlewaretoken
    for POST requests that have an active session.
    """
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if request.method == 'POST':
            try:
                session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
@@ -61,6 +48,12 @@ class CsrfMiddleware(object):

        return None

class CsrfResponseMiddleware(object):
    """
    Middleware that post-processes a response to add a
    csrfmiddlewaretoken if the response/request have an active
    session.
    """
    def process_response(self, request, response):
        csrf_token = None
        try:
@@ -92,3 +85,25 @@ class CsrfMiddleware(object):
            # Modify any POST forms
            response.content = _POST_FORM_RE.sub(add_csrf_field, response.content)
        return response

class CsrfMiddleware(CsrfViewMiddleware, CsrfResponseMiddleware):
    """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.

    CsrfMiddleWare is composed of two middleware, CsrfViewMiddleware
    and CsrfResponseMiddleware which can be used independently.
    """
    pass
+8 −3
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ from django.http import HttpRequest, HttpResponse, HttpResponseForbidden
from django.contrib.csrf.middleware import CsrfMiddleware, _make_token
from django.conf import settings


class CsrfMiddlewareTest(TestCase):

    _session_id = "1"
@@ -46,6 +47,10 @@ class CsrfMiddlewareTest(TestCase):
    def _check_token_present(self, response):
        self.assertContains(response, "name='csrfmiddlewaretoken' value='%s'" % _make_token(self._session_id))

    def get_view(self):
        def dummyview(request):
            return self._get_post_form_response()

    # Check the post processing
    def test_process_response_no_session(self):
        """
@@ -86,7 +91,7 @@ class CsrfMiddlewareTest(TestCase):
        to the incoming request.
        """
        req = self._get_POST_no_session_request()
        req2 = CsrfMiddleware().process_request(req)
        req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})
        self.assertEquals(None, req2)

    def test_process_request_session_no_token(self):
@@ -94,7 +99,7 @@ class CsrfMiddlewareTest(TestCase):
        Check that if a session is present but no token, we get a 'forbidden'
        """
        req = self._get_POST_session_request()
        req2 = CsrfMiddleware().process_request(req)
        req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})
        self.assertEquals(HttpResponseForbidden, req2.__class__)

    def test_process_request_session_and_token(self):
@@ -102,5 +107,5 @@ class CsrfMiddlewareTest(TestCase):
        Check that if a session is present and a token, the middleware lets it through
        """
        req = self._get_POST_session_request_with_token()
        req2 = CsrfMiddleware().process_request(req)
        req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})
        self.assertEquals(None, req2)