Fixed #29728 -- Prevented session resaving if CSRF cookie is unchanged.

This commit is contained in:
Michal Čihař 2018-09-01 16:32:35 +02:00 committed by Tim Graham
parent f315d0423a
commit 22e8ab0286
2 changed files with 17 additions and 3 deletions

View File

@ -181,6 +181,7 @@ class CsrfViewMiddleware(MiddlewareMixin):
def _set_token(self, request, response): def _set_token(self, request, response):
if settings.CSRF_USE_SESSIONS: if settings.CSRF_USE_SESSIONS:
if request.session.get(CSRF_SESSION_KEY) != request.META['CSRF_COOKIE']:
request.session[CSRF_SESSION_KEY] = request.META['CSRF_COOKIE'] request.session[CSRF_SESSION_KEY] = request.META['CSRF_COOKIE']
else: else:
response.set_cookie( response.set_cookie(

View File

@ -1,6 +1,7 @@
import re import re
from django.conf import settings from django.conf import settings
from django.contrib.sessions.backends.cache import SessionStore
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.http import HttpRequest from django.http import HttpRequest
from django.middleware.csrf import ( from django.middleware.csrf import (
@ -24,8 +25,7 @@ class TestingHttpRequest(HttpRequest):
""" """
def __init__(self): def __init__(self):
super().__init__() super().__init__()
# A real session backend isn't needed. self.session = SessionStore()
self.session = {}
def is_secure(self): def is_secure(self):
return getattr(self, '_is_secure_override', False) return getattr(self, '_is_secure_override', False)
@ -693,6 +693,19 @@ class CsrfViewMiddlewareUseSessionsTests(CsrfViewMiddlewareTestMixin, SimpleTest
ensure_csrf_cookie_view(req) ensure_csrf_cookie_view(req)
self.assertTrue(req.session.get(CSRF_SESSION_KEY, False)) self.assertTrue(req.session.get(CSRF_SESSION_KEY, False))
def test_session_modify(self):
"""The session isn't saved if the CSRF cookie is unchanged."""
req = self._get_GET_no_csrf_cookie_request()
self.mw.process_view(req, ensure_csrf_cookie_view, (), {})
resp = ensure_csrf_cookie_view(req)
self.mw.process_response(req, resp)
self.assertIsNotNone(req.session.get(CSRF_SESSION_KEY))
req.session.modified = False
self.mw.process_view(req, ensure_csrf_cookie_view, (), {})
resp = ensure_csrf_cookie_view(req)
self.mw.process_response(req, resp)
self.assertFalse(req.session.modified)
def test_ensures_csrf_cookie_with_middleware(self): def test_ensures_csrf_cookie_with_middleware(self):
""" """
The ensure_csrf_cookie() decorator works with the CsrfViewMiddleware The ensure_csrf_cookie() decorator works with the CsrfViewMiddleware