Loading django/middleware/cache.py +9 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,8 @@ More details about how the caching works: from django.conf import settings from django.core.cache import get_cache, DEFAULT_CACHE_ALIAS from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age from django.utils.cache import (get_cache_key, get_max_age, has_vary_header, learn_cache_key, patch_response_headers) class UpdateCacheMiddleware(object): Loading Loading @@ -93,8 +94,15 @@ class UpdateCacheMiddleware(object): if not self._should_update_cache(request, response): # We don't need to update the cache, just return. return response if response.streaming or response.status_code != 200: return response # Don't cache responses that set a user-specific (and maybe security # sensitive) cookie in response to a cookie-less request. if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'): return response # Try to get the timeout from the "max-age" section of the "Cache- # Control" header before reverting to using the default cache_timeout # length. Loading tests/regressiontests/cache/tests.py +27 −0 Original line number Diff line number Diff line Loading @@ -18,11 +18,13 @@ from django.core import management from django.core.cache import get_cache from django.core.cache.backends.base import (CacheKeyWarning, InvalidCacheBackendError) from django.core.context_processors import csrf from django.db import router from django.http import (HttpResponse, HttpRequest, StreamingHttpResponse, QueryDict) from django.middleware.cache import (FetchFromCacheMiddleware, UpdateCacheMiddleware, CacheMiddleware) from django.middleware.csrf import CsrfViewMiddleware from django.template import Template from django.template.response import TemplateResponse from django.test import TestCase, TransactionTestCase, RequestFactory Loading Loading @@ -1456,6 +1458,10 @@ def hello_world_view(request, value): return HttpResponse('Hello World %s' % value) def csrf_view(request): return HttpResponse(csrf(request)['csrf_token']) @override_settings( CACHE_MIDDLEWARE_ALIAS='other', CACHE_MIDDLEWARE_KEY_PREFIX='middlewareprefix', Loading Loading @@ -1696,6 +1702,27 @@ class CacheMiddlewareTest(TestCase): response = other_with_timeout_view(request, '18') self.assertEqual(response.content, b'Hello World 18') def test_sensitive_cookie_not_cached(self): """ Django must prevent caching of responses that set a user-specific (and maybe security sensitive) cookie in response to a cookie-less request. """ csrf_middleware = CsrfViewMiddleware() cache_middleware = CacheMiddleware() request = self.factory.get('/view/') self.assertIsNone(cache_middleware.process_request(request)) csrf_middleware.process_view(request, csrf_view, (), {}) response = csrf_view(request) response = csrf_middleware.process_response(request, response) response = cache_middleware.process_response(request, response) # Inserting a CSRF cookie in a cookie-less request prevented caching. self.assertIsNone(cache_middleware.process_request(request)) @override_settings( CACHE_MIDDLEWARE_KEY_PREFIX='settingsprefix', Loading Loading
django/middleware/cache.py +9 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,8 @@ More details about how the caching works: from django.conf import settings from django.core.cache import get_cache, DEFAULT_CACHE_ALIAS from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age from django.utils.cache import (get_cache_key, get_max_age, has_vary_header, learn_cache_key, patch_response_headers) class UpdateCacheMiddleware(object): Loading Loading @@ -93,8 +94,15 @@ class UpdateCacheMiddleware(object): if not self._should_update_cache(request, response): # We don't need to update the cache, just return. return response if response.streaming or response.status_code != 200: return response # Don't cache responses that set a user-specific (and maybe security # sensitive) cookie in response to a cookie-less request. if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'): return response # Try to get the timeout from the "max-age" section of the "Cache- # Control" header before reverting to using the default cache_timeout # length. Loading
tests/regressiontests/cache/tests.py +27 −0 Original line number Diff line number Diff line Loading @@ -18,11 +18,13 @@ from django.core import management from django.core.cache import get_cache from django.core.cache.backends.base import (CacheKeyWarning, InvalidCacheBackendError) from django.core.context_processors import csrf from django.db import router from django.http import (HttpResponse, HttpRequest, StreamingHttpResponse, QueryDict) from django.middleware.cache import (FetchFromCacheMiddleware, UpdateCacheMiddleware, CacheMiddleware) from django.middleware.csrf import CsrfViewMiddleware from django.template import Template from django.template.response import TemplateResponse from django.test import TestCase, TransactionTestCase, RequestFactory Loading Loading @@ -1456,6 +1458,10 @@ def hello_world_view(request, value): return HttpResponse('Hello World %s' % value) def csrf_view(request): return HttpResponse(csrf(request)['csrf_token']) @override_settings( CACHE_MIDDLEWARE_ALIAS='other', CACHE_MIDDLEWARE_KEY_PREFIX='middlewareprefix', Loading Loading @@ -1696,6 +1702,27 @@ class CacheMiddlewareTest(TestCase): response = other_with_timeout_view(request, '18') self.assertEqual(response.content, b'Hello World 18') def test_sensitive_cookie_not_cached(self): """ Django must prevent caching of responses that set a user-specific (and maybe security sensitive) cookie in response to a cookie-less request. """ csrf_middleware = CsrfViewMiddleware() cache_middleware = CacheMiddleware() request = self.factory.get('/view/') self.assertIsNone(cache_middleware.process_request(request)) csrf_middleware.process_view(request, csrf_view, (), {}) response = csrf_view(request) response = csrf_middleware.process_response(request, response) response = cache_middleware.process_response(request, response) # Inserting a CSRF cookie in a cookie-less request prevented caching. self.assertIsNone(cache_middleware.process_request(request)) @override_settings( CACHE_MIDDLEWARE_KEY_PREFIX='settingsprefix', Loading