      header to the outgoing response.  For this reason, you may need to use this
      function lazily, as is done by the csrf context processor.
      """
      if "CSRF_COOKIE" not in request.META:
          request.META["CSRF_COOKIE"] = _get_new_csrf_key()
      request.META["CSRF_COOKIE_USED"] = True
      return request.META["CSRF_COOKIE"]
  
  
  def rotate_token(request):
 
</s> remove     return request.META["CSRF_COOKIE"]
 </s> add     return _salt_cipher_secret(csrf_secret) </s> remove    outgoing POST forms.  The value of this field is the value of the CSRF
   cookie.
 </s> add    outgoing POST forms. The value of this field is, again, the value of the
   secret, with a salt which is both added to it and used to scramble it. The
   salt is regenerated on every call to ``get_token()`` so that the form field
   value is changed in every such response. </s> remove                 # nonce we're using. So the MITM can circumvent the CSRF
 </s> add                 # secret we're using. So the MITM can circumvent the CSRF </s> remove    For security reasons, the value of the CSRF cookie is changed each time a
 </s> add    In order to protect against `BREACH`_ attacks, the token is not simply the
   secret; a random salt is prepended to the secret and used to scramble it.

   For security reasons, the value of the secret is changed each time a
        csrf_secret = _get_new_csrf_string()
        request.META["CSRF_COOKIE"] = _salt_cipher_secret(csrf_secret)
    else:
        csrf_secret = _unsalt_cipher_token(request.META["CSRF_COOKIE"])
      header to the outgoing response.  For this reason, you may need to use this
      function lazily, as is done by the csrf context processor.
      """
      if "CSRF_COOKIE" not in request.META:
        csrf_secret = _get_new_csrf_string()
        request.META["CSRF_COOKIE"] = _salt_cipher_secret(csrf_secret)
    else:
        csrf_secret = _unsalt_cipher_token(request.META["CSRF_COOKIE"])
      request.META["CSRF_COOKIE_USED"] = True
      return request.META["CSRF_COOKIE"]
  
  
  def rotate_token(request):
keep keep keep keep replace keep keep keep keep keep
 Fixed #20869 -- made CSRF tokens change every request by salt-encrypting them

Note that the cookie is not changed every request, just the token retrieved
by the `get_token()` method (used also by the `{% csrf_token %}` tag).

While at it, made token validation strict: Where, before, any length was
accepted and non-ASCII chars were ignored, we now treat anything other than
`[A-Za-z0-9]{64}` as invalid (except for 32-char tokens, which, for
backwards-compatibility, are accepted and replaced by 64-char ones).

Thanks Trac user patrys for reporting, github user adambrenecki
for initial patch, Tim Graham for help, and Curtis Maloney,
Collin Anderson, Florian Apolloner, Markus Holtermann & Jon Dufresne
for reviews. 
django/middleware/csrf.py