Ticket #9356: ticket_9356.2.diff

File ticket_9356.2.diff, 6.7 KB (added by Luke Plant, 15 years ago)

Updated patch (but please see my comment)

  • django/contrib/csrf/middleware.py

     
    2727def _make_token(session_id):
    2828    return md5_constructor(settings.SECRET_KEY + session_id).hexdigest()
    2929
     30def _get_validated_session_id(request):
     31    # This function might be called by a template tag. So, we don't make the
     32    # session framework a requirement, otherwise people would have to change
     33    # their templates if they disabled the session middleware
     34    if hasattr(request, 'session'):
     35        # Code that can create a session key will update
     36        # request.session.session_key, so we don't need to check the outgoing
     37        # response for cookies, request.session will reflect the same
     38        # information.
     39        if request.session.accessed or request.session.modified:
     40            # Could be a new session, need to use new session ID
     41            return request.session.session_key
     42        else:
     43            # Avoid use of session.session_key, which can trigger
     44            # unecessary work
     45            session_id = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
     46            if session_id is not None and request.session.exists(session_id):
     47                return session_id
     48            else:
     49                return None # not a valid session
     50    return None
     51
    3052class CsrfViewMiddleware(object):
    3153    """
    3254    Middleware that requires a present and correct csrfmiddlewaretoken
     
    4062            if request.is_ajax():
    4163                return None
    4264
    43             try:
    44                 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
    45             except KeyError:
     65            session_id = _get_validated_session_id(request)
     66            if session_id is None:
    4667                # No session, no check required
    4768                return None
    4869
     
    6990            return response
    7091
    7192        csrf_token = None
    72         try:
    73             # This covers a corner case in which the outgoing response
    74             # both contains a form and sets a session cookie.  This
    75             # really should not be needed, since it is best if views
    76             # that create a new session (login pages) also do a
    77             # redirect, as is done by all such view functions in
    78             # Django.
    79             cookie = response.cookies[settings.SESSION_COOKIE_NAME]
    80             csrf_token = _make_token(cookie.value)
    81         except KeyError:
    82             # Normal case - look for existing session cookie
    83             try:
    84                 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
    85                 csrf_token = _make_token(session_id)
    86             except KeyError:
    87                 # no incoming or outgoing cookie
    88                 pass
     93        session_id = _get_validated_session_id(request)
     94        if session_id is not None:
     95            csrf_token = _make_token(session_id)
    8996
    9097        if csrf_token is not None and \
    9198                response['Content-Type'].split(';')[0] in _HTML_TYPES:
  • django/contrib/csrf/tests.py

     
    11# -*- coding: utf-8 -*-
    22
     3from django.conf import settings
     4from django.contrib.csrf.middleware import CsrfMiddleware, _make_token, csrf_exempt
     5from django.contrib.sessions.middleware import SessionMiddleware
     6from django.http import HttpRequest, HttpResponse, HttpResponseForbidden
    37from django.test import TestCase
    4 from django.http import HttpRequest, HttpResponse, HttpResponseForbidden
    5 from django.contrib.csrf.middleware import CsrfMiddleware, _make_token, csrf_exempt
    6 from django.conf import settings
     8from django.utils.importlib import import_module
    79
    810
    911def post_form_response():
     
    1719
    1820class CsrfMiddlewareTest(TestCase):
    1921
    20     _session_id = "1"
     22    def setUp(self, *args, **kwargs):
     23        super(CsrfMiddlewareTest, self).setUp(*args, **kwargs)
     24        # We have to create an actual session in the DB as the
     25        # middleware validates the session
     26        engine = import_module(settings.SESSION_ENGINE)
     27        s = engine.SessionStore(None)
     28        s.create()
     29        self._session_id = s.session_key
    2130
     31    def _apply_request_middleware(self, req):
     32        SessionMiddleware().process_request(req)
     33        return req
     34
    2235    def _get_GET_no_session_request(self):
    23         return HttpRequest()
     36        return self._apply_request_middleware(HttpRequest())
    2437
    2538    def _get_GET_session_request(self):
    26         req = self._get_GET_no_session_request()
     39        req = HttpRequest()
    2740        req.COOKIES[settings.SESSION_COOKIE_NAME] = self._session_id
    28         return req
     41        return self._apply_request_middleware(req)
    2942
    3043    def _get_POST_session_request(self):
    31         req = self._get_GET_session_request()
     44        req = HttpRequest()
     45        req.COOKIES[settings.SESSION_COOKIE_NAME] = self._session_id
    3246        req.method = "POST"
    33         return req
     47        return self._apply_request_middleware(req)
    3448
    3549    def _get_POST_no_session_request(self):
    36         req = self._get_GET_no_session_request()
     50        req = HttpRequest()
    3751        req.method = "POST"
    38         return req
     52        return self._apply_request_middleware(req)
    3953
    4054    def _get_POST_session_request_with_token(self):
    4155        req = self._get_POST_session_request()
     
    5064        resp.cookies[settings.SESSION_COOKIE_NAME] = self._session_id
    5165        return resp
    5266
    53     def _check_token_present(self, response):
    54         self.assertContains(response, "name='csrfmiddlewaretoken' value='%s'" % _make_token(self._session_id))
     67    def _check_token_present(self, response, session_id=None):
     68        if session_id is None:
     69            session_id = self._session_id
     70        self.assertContains(response, "name='csrfmiddlewaretoken' value='%s'" % _make_token(session_id))
    5571
    5672    def get_view(self):
    5773        return test_view
     
    8399        Check that the token is inserted if there is a new session being started
    84100        """
    85101        req = self._get_GET_no_session_request() # no session in request
    86         resp = self._get_new_session_response() # but new session started
     102        req.session.create() # but new session started
     103        resp = self._get_post_form_response()
    87104        resp_content = resp.content # needed because process_response modifies resp
    88105        resp2 = CsrfMiddleware().process_response(req, resp)
    89106        self.assertNotEqual(resp_content, resp2.content)
    90         self._check_token_present(resp2)
     107        self._check_token_present(resp2, session_id=req.session.session_key)
    91108
    92109    def test_process_response_exempt_view(self):
    93110        """
Back to Top