mirror of
https://github.com/django/django.git
synced 2025-04-01 12:06:43 +00:00
Fixed #24696 -- Made CSRF_COOKIE computation lazy.
Only compute the CSRF_COOKIE when it is actually used. This is a significant speedup for clients not using cookies. Changed result of the “test_token_node_no_csrf_cookie” test: It gets a valid CSRF token now which seems like the correct behavior. Changed auth_tests.test_views.LoginTest.test_login_csrf_rotate to use get_token() to trigger CSRF cookie inclusion instead of changing request.META["CSRF_COOKIE_USED"] directly.
This commit is contained in:
parent
0894643e40
commit
eef95ea96f
@ -40,15 +40,17 @@ def _get_new_csrf_key():
|
|||||||
def get_token(request):
|
def get_token(request):
|
||||||
"""
|
"""
|
||||||
Returns the CSRF token required for a POST form. The token is an
|
Returns the CSRF token required for a POST form. The token is an
|
||||||
alphanumeric value.
|
alphanumeric value. A new token is created if one is not already set.
|
||||||
|
|
||||||
A side effect of calling this function is to make the csrf_protect
|
A side effect of calling this function is to make the csrf_protect
|
||||||
decorator and the CsrfViewMiddleware add a CSRF cookie and a 'Vary: Cookie'
|
decorator and the CsrfViewMiddleware add a CSRF cookie and a 'Vary: Cookie'
|
||||||
header to the outgoing response. For this reason, you may need to use this
|
header to the outgoing response. For this reason, you may need to use this
|
||||||
function lazily, as is done by the csrf context processor.
|
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
|
request.META["CSRF_COOKIE_USED"] = True
|
||||||
return request.META.get("CSRF_COOKIE", None)
|
return request.META["CSRF_COOKIE"]
|
||||||
|
|
||||||
|
|
||||||
def rotate_token(request):
|
def rotate_token(request):
|
||||||
@ -112,9 +114,6 @@ class CsrfViewMiddleware(object):
|
|||||||
request.META['CSRF_COOKIE'] = csrf_token
|
request.META['CSRF_COOKIE'] = csrf_token
|
||||||
except KeyError:
|
except KeyError:
|
||||||
csrf_token = None
|
csrf_token = None
|
||||||
# Generate token and store it in the request, so it's
|
|
||||||
# available to the view.
|
|
||||||
request.META["CSRF_COOKIE"] = _get_new_csrf_key()
|
|
||||||
|
|
||||||
# Wait until request.META["CSRF_COOKIE"] has been manipulated before
|
# Wait until request.META["CSRF_COOKIE"] has been manipulated before
|
||||||
# bailing out, so that get_token still works
|
# bailing out, so that get_token still works
|
||||||
@ -194,12 +193,6 @@ class CsrfViewMiddleware(object):
|
|||||||
if getattr(response, 'csrf_processing_done', False):
|
if getattr(response, 'csrf_processing_done', False):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
# If CSRF_COOKIE is unset, then CsrfViewMiddleware.process_view was
|
|
||||||
# never called, probably because a request middleware returned a response
|
|
||||||
# (for example, contrib.auth redirecting to a login page).
|
|
||||||
if request.META.get("CSRF_COOKIE") is None:
|
|
||||||
return response
|
|
||||||
|
|
||||||
if not request.META.get("CSRF_COOKIE_USED", False):
|
if not request.META.get("CSRF_COOKIE_USED", False):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ from django.core import mail
|
|||||||
from django.core.urlresolvers import NoReverseMatch, reverse, reverse_lazy
|
from django.core.urlresolvers import NoReverseMatch, reverse, reverse_lazy
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.http import HttpRequest, QueryDict
|
from django.http import HttpRequest, QueryDict
|
||||||
from django.middleware.csrf import CsrfViewMiddleware
|
from django.middleware.csrf import CsrfViewMiddleware, get_token
|
||||||
from django.test import (
|
from django.test import (
|
||||||
TestCase, ignore_warnings, modify_settings, override_settings,
|
TestCase, ignore_warnings, modify_settings, override_settings,
|
||||||
)
|
)
|
||||||
@ -606,7 +606,8 @@ class LoginTest(AuthViewsTestCase):
|
|||||||
# TestClient isn't used here as we're testing middleware, essentially.
|
# TestClient isn't used here as we're testing middleware, essentially.
|
||||||
req = HttpRequest()
|
req = HttpRequest()
|
||||||
CsrfViewMiddleware().process_view(req, login_view, (), {})
|
CsrfViewMiddleware().process_view(req, login_view, (), {})
|
||||||
req.META["CSRF_COOKIE_USED"] = True
|
# get_token() triggers CSRF token inclusion in the response
|
||||||
|
get_token(req)
|
||||||
resp = login_view(req)
|
resp = login_view(req)
|
||||||
resp2 = CsrfViewMiddleware().process_response(req, resp)
|
resp2 = CsrfViewMiddleware().process_response(req, resp)
|
||||||
csrf_cookie = resp2.cookies.get(settings.CSRF_COOKIE_NAME, None)
|
csrf_cookie = resp2.cookies.get(settings.CSRF_COOKIE_NAME, None)
|
||||||
|
@ -5,7 +5,9 @@ import logging
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.middleware.csrf import CSRF_KEY_LENGTH, CsrfViewMiddleware
|
from django.middleware.csrf import (
|
||||||
|
CSRF_KEY_LENGTH, CsrfViewMiddleware, get_token,
|
||||||
|
)
|
||||||
from django.template import RequestContext, Template
|
from django.template import RequestContext, Template
|
||||||
from django.template.context_processors import csrf
|
from django.template.context_processors import csrf
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
@ -237,7 +239,10 @@ class CsrfViewMiddlewareTest(TestCase):
|
|||||||
"""
|
"""
|
||||||
req = self._get_GET_no_csrf_cookie_request()
|
req = self._get_GET_no_csrf_cookie_request()
|
||||||
resp = token_view(req)
|
resp = token_view(req)
|
||||||
self.assertEqual(resp.content, b'')
|
|
||||||
|
token = get_token(req)
|
||||||
|
self.assertIsNotNone(token)
|
||||||
|
self._check_token_present(resp, token)
|
||||||
|
|
||||||
def test_token_node_empty_csrf_cookie(self):
|
def test_token_node_empty_csrf_cookie(self):
|
||||||
"""
|
"""
|
||||||
@ -248,7 +253,9 @@ class CsrfViewMiddlewareTest(TestCase):
|
|||||||
CsrfViewMiddleware().process_view(req, token_view, (), {})
|
CsrfViewMiddleware().process_view(req, token_view, (), {})
|
||||||
resp = token_view(req)
|
resp = token_view(req)
|
||||||
|
|
||||||
self.assertNotEqual("", resp.content)
|
token = get_token(req)
|
||||||
|
self.assertIsNotNone(token)
|
||||||
|
self._check_token_present(resp, token)
|
||||||
|
|
||||||
def test_token_node_with_csrf_cookie(self):
|
def test_token_node_with_csrf_cookie(self):
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user