Refs #26902 -- Protected against insecure redirects in Login/LogoutView.
This commit is contained in:
parent
5e5a17028f
commit
549b90fab3
|
@ -84,7 +84,12 @@ class LoginView(FormView):
|
|||
self.redirect_field_name,
|
||||
self.request.GET.get(self.redirect_field_name, '')
|
||||
)
|
||||
if not is_safe_url(url=redirect_to, host=self.request.get_host()):
|
||||
url_is_safe = is_safe_url(
|
||||
url=redirect_to,
|
||||
host=self.request.get_host(),
|
||||
require_https=self.request.is_secure(),
|
||||
)
|
||||
if not url_is_safe:
|
||||
return resolve_url(settings.LOGIN_REDIRECT_URL)
|
||||
return redirect_to
|
||||
|
||||
|
@ -150,8 +155,13 @@ class LogoutView(TemplateView):
|
|||
self.redirect_field_name,
|
||||
self.request.GET.get(self.redirect_field_name)
|
||||
)
|
||||
url_is_safe = is_safe_url(
|
||||
url=next_page,
|
||||
host=self.request.get_host(),
|
||||
require_https=self.request.is_secure(),
|
||||
)
|
||||
# Security check -- don't allow redirection to a different host.
|
||||
if not is_safe_url(url=next_page, host=self.request.get_host()):
|
||||
if not url_is_safe:
|
||||
next_page = self.request.path
|
||||
return next_page
|
||||
|
||||
|
|
|
@ -356,6 +356,13 @@ to assign a free port. The ``DJANGO_LIVE_TEST_SERVER_ADDRESS`` environment
|
|||
variable is no longer used, and as it's also no longer used, the
|
||||
``manage.py test --liveserver`` option is removed.
|
||||
|
||||
Protection against insecure redirects in :mod:`django.contrib.auth` views
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
``LoginView`` and ``LogoutView`` (and the deprecated function-based equivalents)
|
||||
protect users from being redirected to non-HTTPS ``next`` URLs when the app
|
||||
is running over HTTPS.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
|
|
|
@ -551,6 +551,23 @@ class LoginTest(AuthViewsTestCase):
|
|||
self.assertEqual(response.status_code, 302)
|
||||
self.assertIn(good_url, response.url, "%s should be allowed" % good_url)
|
||||
|
||||
def test_security_check_https(self):
|
||||
login_url = reverse('login')
|
||||
non_https_next_url = 'http://testserver/path'
|
||||
not_secured_url = '%(url)s?%(next)s=%(next_url)s' % {
|
||||
'url': login_url,
|
||||
'next': REDIRECT_FIELD_NAME,
|
||||
'next_url': urlquote(non_https_next_url),
|
||||
}
|
||||
post_data = {
|
||||
'username': 'testclient',
|
||||
'password': 'password',
|
||||
}
|
||||
response = self.client.post(not_secured_url, post_data, secure=True)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertNotEqual(response.url, non_https_next_url)
|
||||
self.assertEqual(response.url, settings.LOGIN_REDIRECT_URL)
|
||||
|
||||
def test_login_form_contains_request(self):
|
||||
# 15198
|
||||
self.client.post('/custom_requestauth_login/', {
|
||||
|
@ -919,6 +936,21 @@ class LogoutTest(AuthViewsTestCase):
|
|||
self.assertIn(good_url, response.url, "%s should be allowed" % good_url)
|
||||
self.confirm_logged_out()
|
||||
|
||||
def test_security_check_https(self):
|
||||
logout_url = reverse('logout')
|
||||
non_https_next_url = 'http://testserver/'
|
||||
url = '%(url)s?%(next)s=%(next_url)s' % {
|
||||
'url': logout_url,
|
||||
'next': REDIRECT_FIELD_NAME,
|
||||
'next_url': urlquote(non_https_next_url),
|
||||
}
|
||||
self.login()
|
||||
response = self.client.get(url, secure=True)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertNotEqual(response.url, non_https_next_url)
|
||||
self.assertEqual(response.url, logout_url)
|
||||
self.confirm_logged_out()
|
||||
|
||||
def test_logout_preserve_language(self):
|
||||
"""Check that language stored in session is preserved after logout"""
|
||||
# Create a new session with language
|
||||
|
|
Loading…
Reference in New Issue