From 2808cdc8fb15ad27f83af3e62db69f5ea7ced29e Mon Sep 17 00:00:00 2001 From: Hasan Ramezani Date: Mon, 7 Sep 2020 13:33:47 +0200 Subject: Fixed #31962 -- Made SessionMiddleware raise SessionInterrupted when session destroyed while request is processing. --- django/contrib/sessions/exceptions.py | 7 ++++++- django/contrib/sessions/middleware.py | 4 ++-- django/core/exceptions.py | 5 +++++ django/core/handlers/exception.py | 13 ++++++++++++- 4 files changed, 25 insertions(+), 4 deletions(-) (limited to 'django') diff --git a/django/contrib/sessions/exceptions.py b/django/contrib/sessions/exceptions.py index 4f4dc6b048..8dbca3d04f 100644 --- a/django/contrib/sessions/exceptions.py +++ b/django/contrib/sessions/exceptions.py @@ -1,4 +1,4 @@ -from django.core.exceptions import SuspiciousOperation +from django.core.exceptions import BadRequest, SuspiciousOperation class InvalidSessionKey(SuspiciousOperation): @@ -9,3 +9,8 @@ class InvalidSessionKey(SuspiciousOperation): class SuspiciousSession(SuspiciousOperation): """The session may be tampered with""" pass + + +class SessionInterrupted(BadRequest): + """The session was interrupted.""" + pass diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py index cb8c1ff45b..50627a663b 100644 --- a/django/contrib/sessions/middleware.py +++ b/django/contrib/sessions/middleware.py @@ -3,7 +3,7 @@ from importlib import import_module from django.conf import settings from django.contrib.sessions.backends.base import UpdateError -from django.core.exceptions import SuspiciousOperation +from django.contrib.sessions.exceptions import SessionInterrupted from django.utils.cache import patch_vary_headers from django.utils.deprecation import MiddlewareMixin from django.utils.http import http_date @@ -60,7 +60,7 @@ class SessionMiddleware(MiddlewareMixin): try: request.session.save() except UpdateError: - raise SuspiciousOperation( + raise SessionInterrupted( "The request's session was deleted before the " "request completed. The user may have logged " "out in a concurrent request, for example." diff --git a/django/core/exceptions.py b/django/core/exceptions.py index 2b3e55fe49..5780ffdb4a 100644 --- a/django/core/exceptions.py +++ b/django/core/exceptions.py @@ -71,6 +71,11 @@ class RequestAborted(Exception): pass +class BadRequest(Exception): + """The request is malformed and cannot be processed.""" + pass + + class PermissionDenied(Exception): """The user did not have permission to do that""" pass diff --git a/django/core/handlers/exception.py b/django/core/handlers/exception.py index 98fb46083a..70b23edb62 100644 --- a/django/core/handlers/exception.py +++ b/django/core/handlers/exception.py @@ -8,7 +8,7 @@ from asgiref.sync import sync_to_async from django.conf import settings from django.core import signals from django.core.exceptions import ( - PermissionDenied, RequestDataTooBig, SuspiciousOperation, + BadRequest, PermissionDenied, RequestDataTooBig, SuspiciousOperation, TooManyFieldsSent, ) from django.http import Http404 @@ -76,6 +76,17 @@ def response_for_exception(request, exc): exc_info=sys.exc_info(), ) + elif isinstance(exc, BadRequest): + if settings.DEBUG: + response = debug.technical_500_response(request, *sys.exc_info(), status_code=400) + else: + response = get_exception_response(request, get_resolver(get_urlconf()), 400, exc) + log_response( + '%s: %s', str(exc), request.path, + response=response, + request=request, + exc_info=sys.exc_info(), + ) elif isinstance(exc, SuspiciousOperation): if isinstance(exc, (RequestDataTooBig, TooManyFieldsSent)): # POST data can't be accessed again, otherwise the original -- cgit v1.3