Fixed #21324 -- Translate CSRF failure view
Thanks to Claude Paroz for the original patch.
This commit is contained in:
parent
090315f5df
commit
6107435386
|
@ -92,8 +92,7 @@ class CsrfViewMiddleware(object):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _reject(self, request, reason):
|
def _reject(self, request, reason):
|
||||||
logger.warning('Forbidden (%s): %s',
|
logger.warning('Forbidden (%s): %s', reason, request.path,
|
||||||
reason, request.path,
|
|
||||||
extra={
|
extra={
|
||||||
'status_code': 403,
|
'status_code': 403,
|
||||||
'request': request,
|
'request': request,
|
||||||
|
@ -184,7 +183,7 @@ class CsrfViewMiddleware(object):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
# If CSRF_COOKIE is unset, then CsrfViewMiddleware.process_view was
|
# If CSRF_COOKIE is unset, then CsrfViewMiddleware.process_view was
|
||||||
# never called, probaby because a request middleware returned a response
|
# never called, probably because a request middleware returned a response
|
||||||
# (for example, contrib.auth redirecting to a login page).
|
# (for example, contrib.auth redirecting to a login page).
|
||||||
if request.META.get("CSRF_COOKIE") is None:
|
if request.META.get("CSRF_COOKIE") is None:
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
|
from django.conf import settings
|
||||||
from django.http import HttpResponseForbidden
|
from django.http import HttpResponseForbidden
|
||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
from django.conf import settings
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
# We include the template inline since we need to be able to reliably display
|
# We include the template inline since we need to be able to reliably display
|
||||||
# this error message, especially for the sake of developers, and there isn't any
|
# this error message, especially for the sake of developers, and there isn't any
|
||||||
# other way of making it available independent of what is in the settings file.
|
# other way of making it available independent of what is in the settings file.
|
||||||
|
|
||||||
|
# Only the text appearing with DEBUG=False is translated. Normal translation
|
||||||
|
# tags cannot be used with this inline templates as makemessages would not be
|
||||||
|
# able to discover the strings.
|
||||||
|
|
||||||
CSRF_FAILURE_TEMPLATE = """
|
CSRF_FAILURE_TEMPLATE = """
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
@ -30,17 +35,11 @@ CSRF_FAILURE_TEMPLATE = """
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="summary">
|
<div id="summary">
|
||||||
<h1>Forbidden <span>(403)</span></h1>
|
<h1>{{ title }} <span>(403)</span></h1>
|
||||||
<p>CSRF verification failed. Request aborted.</p>
|
<p>{{ main }}</p>
|
||||||
{% if no_referer %}
|
{% if no_referer %}
|
||||||
<p>You are seeing this message because this HTTPS site requires a 'Referer
|
<p>{{ no_referer1 }}</p>
|
||||||
header' to be sent by your Web browser, but none was sent. This header is
|
<p>{{ no_referer2 }}</p>
|
||||||
required for security reasons, to ensure that your browser is not being
|
|
||||||
hijacked by third parties.</p>
|
|
||||||
|
|
||||||
<p>If you have configured your browser to disable 'Referer' headers, please
|
|
||||||
re-enable them, at least for this site, or for HTTPS connections, or for
|
|
||||||
'same-origin' requests.</p>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if DEBUG %}
|
{% if DEBUG %}
|
||||||
|
@ -84,21 +83,35 @@ CSRF_FAILURE_TEMPLATE = """
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div id="explanation">
|
<div id="explanation">
|
||||||
<p><small>More information is available with DEBUG=True.</small></p>
|
<p><small>{{ more }}</small></p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def csrf_failure(request, reason=""):
|
def csrf_failure(request, reason=""):
|
||||||
"""
|
"""
|
||||||
Default view used when request fails CSRF protection
|
Default view used when request fails CSRF protection
|
||||||
"""
|
"""
|
||||||
from django.middleware.csrf import REASON_NO_REFERER
|
from django.middleware.csrf import REASON_NO_REFERER
|
||||||
t = Template(CSRF_FAILURE_TEMPLATE)
|
t = Template(CSRF_FAILURE_TEMPLATE)
|
||||||
c = Context({'DEBUG': settings.DEBUG,
|
c = Context({
|
||||||
'reason': reason,
|
'title': _("Forbidden"),
|
||||||
'no_referer': reason == REASON_NO_REFERER
|
'main': _("CSRF verification failed. Request aborted."),
|
||||||
})
|
'reason': reason,
|
||||||
|
'no_referer': reason == REASON_NO_REFERER,
|
||||||
|
'no_referer1': _(
|
||||||
|
"You are seeing this message because this HTTPS site requires a "
|
||||||
|
"'Referer header' to be sent by your Web browser, but none was "
|
||||||
|
"sent. This header is required for security reasons, to ensure "
|
||||||
|
"that your browser is not being hijacked by third parties."),
|
||||||
|
'no_referer2': _(
|
||||||
|
"If you have configured your browser to disable 'Referer' headers, "
|
||||||
|
"please re-enable them, at least for this site, or for HTTPS "
|
||||||
|
"connections, or for 'same-origin' requests."),
|
||||||
|
'DEBUG': settings.DEBUG,
|
||||||
|
'more': _("More information is available with DEBUG=True."),
|
||||||
|
})
|
||||||
return HttpResponseForbidden(t.render(c), content_type='text/html')
|
return HttpResponseForbidden(t.render(c), content_type='text/html')
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,25 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-09-15 19:15+0200\n"
|
||||||
|
"PO-Revision-Date: 2010-05-12 12:41-0300\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: views/csrf.py:98
|
||||||
|
msgid "Forbidden"
|
||||||
|
msgstr "Verboden"
|
||||||
|
|
||||||
|
#: views/csrf.py:99
|
||||||
|
msgid "CSRF verification failed. Request aborted."
|
||||||
|
msgstr "CSRF-verificatie mislukt. Verzoek afgebroken."
|
|
@ -0,0 +1,33 @@
|
||||||
|
from django.test import TestCase, override_settings, Client
|
||||||
|
from django.utils.translation import override
|
||||||
|
|
||||||
|
|
||||||
|
class CsrfViewTests(TestCase):
|
||||||
|
urls = "view_tests.urls"
|
||||||
|
|
||||||
|
@override_settings(
|
||||||
|
USE_I18N=True,
|
||||||
|
MIDDLEWARE_CLASSES=(
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_translation(self):
|
||||||
|
"""
|
||||||
|
Test that an invalid request is rejected with a localized error message.
|
||||||
|
"""
|
||||||
|
self.client = Client(enforce_csrf_checks=True)
|
||||||
|
|
||||||
|
response = self.client.post('/', HTTP_HOST='www.example.com')
|
||||||
|
self.assertContains(response, "Forbidden", status_code=403)
|
||||||
|
self.assertContains(response,
|
||||||
|
"CSRF verification failed. Request aborted.",
|
||||||
|
status_code=403)
|
||||||
|
|
||||||
|
with self.settings(LANGUAGE_CODE='nl'), override('en-us'):
|
||||||
|
response = self.client.post('/', HTTP_HOST='www.example.com')
|
||||||
|
self.assertContains(response, "Verboden", status_code=403)
|
||||||
|
self.assertContains(response,
|
||||||
|
"CSRF-verificatie mislukt. Verzoek afgebroken.",
|
||||||
|
status_code=403)
|
Loading…
Reference in New Issue