diff --git a/django/middleware/cache.py b/django/middleware/cache.py
index a3076ac..68345cc 100644
--- a/django/middleware/cache.py
+++ b/django/middleware/cache.py
@@ -50,7 +50,7 @@ More details about how the caching works:
 
 from django.conf import settings
 from django.core.cache import cache
-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, learn_cache_key, patch_response_headers, get_max_age, has_vary_header
 
 class UpdateCacheMiddleware(object):
     """
@@ -66,9 +66,19 @@ class UpdateCacheMiddleware(object):
         self.key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
         self.cache_anonymous_only = getattr(settings, 'CACHE_MIDDLEWARE_ANONYMOUS_ONLY', False)
 
+    def _should_update_cache(self, request, response):
+        if not hasattr(request, '_cache_update_cache') or not request._cache_update_cache:
+            return False
+        if self.cache_anonymous_only and has_vary_header(response, 'Cookie'):
+            assert hasattr(request, 'user'), "The Django cache middleware with CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' before the CacheMiddleware."
+            if request.user.is_authenticated():
+                # Don't cache user-variable requests from authenticated users.
+                return False
+        return True
+
     def process_response(self, request, response):
         """Sets the cache, if needed."""
-        if not hasattr(request, '_cache_update_cache') or not request._cache_update_cache:
+        if not self._should_update_cache(request, response):
             # We don't need to update the cache, just return.
             return response
         if not response.status_code == 200:
@@ -106,17 +116,10 @@ class FetchFromCacheMiddleware(object):
         Checks whether the page is already cached and returns the cached
         version if available.
         """
-        if self.cache_anonymous_only:
-            assert hasattr(request, 'user'), "The Django cache middleware with CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' before the CacheMiddleware."
-
         if not request.method in ('GET', 'HEAD') or request.GET:
             request._cache_update_cache = False
             return None # Don't bother checking the cache.
 
-        if self.cache_anonymous_only and request.user.is_authenticated():
-            request._cache_update_cache = False
-            return None # Don't cache requests from authenticated users.
-
         # try and get the cached GET response
         cache_key = get_cache_key(request, self.key_prefix, 'GET')
 
diff --git a/django/utils/cache.py b/django/utils/cache.py
index b1b35b5..a2e7d6b 100644
--- a/django/utils/cache.py
+++ b/django/utils/cache.py
@@ -134,6 +134,16 @@ def patch_vary_headers(response, newheaders):
                           if newheader.lower() not in existing_headers]
     response['Vary'] = ', '.join(vary_headers + additional_headers)
 
+def has_vary_header(response, header_query):
+    """
+    Checks to see if the response has a given header name in its Vary header.
+    """
+    if not response.has_header('Vary'):
+        return False
+    vary_headers = cc_delim_re.split(response['Vary'])
+    existing_headers = set([header.lower() for header in vary_headers])
+    return header_query.lower() in existing_headers
+
 def _i18n_cache_key_suffix(request, cache_key):
     """If enabled, returns the cache key ending with a locale."""
     if settings.USE_I18N:
diff --git a/docs/topics/cache.txt b/docs/topics/cache.txt
index f2b7a59..2fdc601 100644
--- a/docs/topics/cache.txt
+++ b/docs/topics/cache.txt
@@ -323,14 +323,14 @@ Then, add the following required settings to your Django settings file:
   collisions. Use an empty string if you don't care.
 
 The cache middleware caches every page that doesn't have GET or POST
-parameters. Optionally, if the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting is
-``True``, only anonymous requests (i.e., not those made by a logged-in user)
-will be cached. This is a simple and effective way of disabling caching for any
-user-specific pages (include Django's admin interface). Note that if you use
-``CACHE_MIDDLEWARE_ANONYMOUS_ONLY``, you should make sure you've activated
-``AuthenticationMiddleware``. The cache middleware expects that a HEAD request
-is answered with the same response headers exactly like the corresponding GET
-request, in that case it could return cached GET response for HEAD request.
+parameters. Pages are cached separately based on the values of the HTTP headers
+they vary by, so user-specific pages will never be shown to the wrong person if
+you're accessing the user's information via
+:attr:`request.user <django.http.HttpRequest.user>`, which results in the
+appropriate ``Vary`` headers being set. The cache middleware expects that a HEAD
+request is answered with the same response headers exactly like the
+corresponding GET request, in that case it could return cached GET response for
+HEAD request.
 
 Additionally, the cache middleware automatically sets a few headers in each
 ``HttpResponse``:
diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py
index da4c9a8..ee9c272 100644
--- a/tests/regressiontests/cache/tests.py
+++ b/tests/regressiontests/cache/tests.py
@@ -15,9 +15,10 @@ from django.core.cache import get_cache
 from django.core.cache.backends.base import InvalidCacheBackendError, CacheKeyWarning
 from django.http import HttpResponse, HttpRequest
 from django.middleware.cache import FetchFromCacheMiddleware, UpdateCacheMiddleware
+from django.test import TestCase
 from django.utils import translation
 from django.utils import unittest
-from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key
+from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key, has_vary_header
 from django.utils.hashcompat import md5_constructor
 from regressiontests.cache.models import Poll, expensive_calculation
 
@@ -544,6 +545,23 @@ class CacheUtils(unittest.TestCase):
             patch_vary_headers(response, newheaders)
             self.assertEqual(response['Vary'], resulting_vary)
 
+    def test_has_vary_header(self):
+        possible_headers = ('cookie', 'accept-encoding')
+        sample_values = (
+            # Vary header value, has_vary_header value for the possible_headers
+            ('Cookie', (True, False)),
+            ('COOKIE', (True, False)),
+            ('Accept-Encoding', (False, True)),
+            ('Cookie, Accept-Encoding', (True, True)),
+            ('Accept-Encoding, Cookie', (True, True)),
+            ('Cookie    ,     Accept-Encoding', (True, True)),
+        )
+        for vary_header, results in sample_values:
+            response = HttpResponse()
+            response['Vary'] = vary_header
+            for test_header, result in zip(possible_headers, results):
+                self.assertEqual(has_vary_header(response, test_header), result)
+
     def test_get_cache_key(self):
         request = self._get_request(self.path)
         response = HttpResponse()
@@ -718,5 +736,27 @@ class CacheI18nTest(unittest.TestCase):
         get_cache_data = FetchFromCacheMiddleware().process_request(request)
         self.assertEqual(get_cache_data.content, es_message)
 
+class CacheMiddlewareTests(TestCase):
+    urls = 'regressiontests.cache.urls'
+
+    def setUp(self):
+        self._orig_cache_middleware_anonymous_only = \
+            getattr(settings, 'CACHE_MIDDLEWARE_ANONYMOUS_ONLY', False)
+        self._orig_middleware_classes = settings.MIDDLEWARE_CLASSES
+
+        settings.MIDDLEWARE_CLASSES = list(settings.MIDDLEWARE_CLASSES)
+        settings.MIDDLEWARE_CLASSES.insert(0, 'django.middleware.cache.UpdateCacheMiddleware')
+        settings.MIDDLEWARE_CLASSES += ['django.middleware.cache.FetchFromCacheMiddleware']
+
+    def tearDown(self):
+        settings.CACHE_MIDDLEWARE_ANONYMOUS_ONLY = self._orig_cache_middleware_anonymous_only
+        settings.MIDDLEWARE_CLASSES = self._orig_middleware_classes
+
+    def test_cache_middleware_anonymous_only_does_not_cause_vary_cookie(self):
+        settings.CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True
+        response = self.client.get('/')
+        self.failIf('Cookie' in response.get('Vary', ''))
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/regressiontests/cache/urls.py b/tests/regressiontests/cache/urls.py
new file mode 100644
index 0000000..78b2125
--- /dev/null
+++ b/tests/regressiontests/cache/urls.py
@@ -0,0 +1,6 @@
+from django.conf.urls.defaults import *
+
+
+urlpatterns = patterns('regressiontests.cache.views',
+    (r'^$', 'home'),
+)
diff --git a/tests/regressiontests/cache/views.py b/tests/regressiontests/cache/views.py
new file mode 100644
index 0000000..d8dc8b6
--- /dev/null
+++ b/tests/regressiontests/cache/views.py
@@ -0,0 +1,5 @@
+from django.http import HttpResponse
+
+
+def home(request):
+    return HttpResponse('Hello World!')
