From 04bc2564b6e0a1a0f75bb5f015e47c96c86fa0be Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sat, 16 Apr 2022 20:21:29 +0200 Subject: [PATCH] Simplified LogoutView.get_success_url(). This preserves the behavior of redirecting to the logout URL without query string parameters when an insecure ?next=... parameter is given. It changes the behavior of a POST to the logout URL, as shown by the test that is changed. Currently, this results in a GET to the logout URL. However, such GET requests are deprecated. This change would be necessary in Django 5.0 anyway. This commit merely anticipates it. --- django/contrib/auth/views.py | 22 +++++----------------- tests/auth_tests/test_views.py | 9 ++++++++- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py index 60ae71b6695..48b27d5a611 100644 --- a/django/contrib/auth/views.py +++ b/django/contrib/auth/views.py @@ -146,8 +146,8 @@ class LogoutView(RedirectURLMixin, TemplateView): """Logout may be done via POST.""" auth_logout(request) redirect_to = self.get_success_url() - if redirect_to: - # Redirect to this page until the session has been cleared. + if redirect_to != request.get_full_path(): + # Redirect to target page once the session has been cleared. return HttpResponseRedirect(redirect_to) return super().get(request, *args, **kwargs) @@ -155,28 +155,16 @@ class LogoutView(RedirectURLMixin, TemplateView): get = post def get_default_redirect_url(self): - """Return the default redirect URL, or None if no URL is configured.""" + """Return the default redirect URL.""" if self.next_page: return resolve_url(self.next_page) elif settings.LOGOUT_REDIRECT_URL: return resolve_url(settings.LOGOUT_REDIRECT_URL) else: - return None + return self.request.path def get_success_url(self): - next_page = self.get_default_redirect_url() - - if ( - self.redirect_field_name in self.request.POST - or self.redirect_field_name in self.request.GET - ): - next_page = self.get_redirect_url() - if next_page == "": - if settings.LOGOUT_REDIRECT_URL: - next_page = resolve_url(settings.LOGOUT_REDIRECT_URL) - else: - next_page = self.request.path - return next_page + return self.get_redirect_url() or self.get_default_redirect_url() def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) diff --git a/tests/auth_tests/test_views.py b/tests/auth_tests/test_views.py index dbff9317537..86424636b7c 100644 --- a/tests/auth_tests/test_views.py +++ b/tests/auth_tests/test_views.py @@ -984,6 +984,8 @@ class LogoutThenLoginTests(AuthViewsTestCase): csrf_token = get_token(req) req.COOKIES[settings.CSRF_COOKIE_NAME] = csrf_token req.POST = {"csrfmiddlewaretoken": csrf_token} + req.META["SERVER_NAME"] = "testserver" + req.META["SERVER_PORT"] = 80 req.session = self.client.session response = logout_then_login(req) self.confirm_logged_out() @@ -996,6 +998,8 @@ class LogoutThenLoginTests(AuthViewsTestCase): csrf_token = get_token(req) req.COOKIES[settings.CSRF_COOKIE_NAME] = csrf_token req.POST = {"csrfmiddlewaretoken": csrf_token} + req.META["SERVER_NAME"] = "testserver" + req.META["SERVER_PORT"] = 80 req.session = self.client.session response = logout_then_login(req, login_url="/custom/") self.confirm_logged_out() @@ -1007,6 +1011,8 @@ class LogoutThenLoginTests(AuthViewsTestCase): self.login() req = HttpRequest() req.method = "GET" + req.META["SERVER_NAME"] = "testserver" + req.META["SERVER_PORT"] = 80 req.session = self.client.session response = logout_then_login(req) # RemovedInDjango50Warning: When the deprecation ends, replace with @@ -1345,7 +1351,8 @@ class LogoutTest(AuthViewsTestCase): def test_logout_redirect_url_named_setting(self): self.login() response = self.client.post("/logout/") - self.assertRedirects(response, "/logout/", fetch_redirect_response=False) + self.assertContains(response, "Logged out") + self.confirm_logged_out() def get_perm(Model, perm):