mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #33569 -- Added SECURE_PROXY_SSL_HEADER support for list of protocols in the header value.
This commit is contained in:
parent
d46e158ee2
commit
1cf60ce601
@ -261,7 +261,8 @@ class HttpRequest:
|
||||
)
|
||||
header_value = self.META.get(header)
|
||||
if header_value is not None:
|
||||
return "https" if header_value == secure_value else "http"
|
||||
header_value, *_ = header_value.split(",", 1)
|
||||
return "https" if header_value.strip() == secure_value else "http"
|
||||
return self._get_scheme()
|
||||
|
||||
def is_secure(self):
|
||||
|
@ -2442,8 +2442,17 @@ required value. For example::
|
||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
|
||||
This tells Django to trust the ``X-Forwarded-Proto`` header that comes from our
|
||||
proxy, and any time its value is ``'https'``, then the request is guaranteed to
|
||||
be secure (i.e., it originally came in via HTTPS).
|
||||
proxy and that the request is guaranteed to be secure (i.e., it originally came
|
||||
in via HTTPS) when:
|
||||
|
||||
* the header value is ``'https'``, or
|
||||
* its initial, leftmost value is ``'https'`` in the case of a comma-separated
|
||||
list of protocols (e.g. ``'https,http,http'``).
|
||||
|
||||
.. versionchanged:: 4.1
|
||||
|
||||
Support for a comma-separated list of protocols in the header value was
|
||||
added.
|
||||
|
||||
You should *only* set this setting if you control your proxy or have some other
|
||||
guarantee that it sets/strips this header appropriately.
|
||||
@ -2463,8 +2472,9 @@ available in ``request.META``.)
|
||||
|
||||
* Your Django app is behind a proxy.
|
||||
* Your proxy strips the ``X-Forwarded-Proto`` header from all incoming
|
||||
requests. In other words, if end users include that header in their
|
||||
requests, the proxy will discard it.
|
||||
requests, even when it contains a comma-separated list of protocols. In
|
||||
other words, if end users include that header in their requests, the
|
||||
proxy will discard it.
|
||||
* Your proxy sets the ``X-Forwarded-Proto`` header and sends it to Django,
|
||||
but only for requests that originally come in via HTTPS.
|
||||
|
||||
|
@ -293,6 +293,9 @@ Security
|
||||
* The new :setting:`SECRET_KEY_FALLBACKS` setting allows providing a list of
|
||||
values for secret key rotation.
|
||||
|
||||
* The :setting:`SECURE_PROXY_SSL_HEADER` setting now supports a comma-separated
|
||||
list of protocols in the header value.
|
||||
|
||||
Serialization
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
@ -424,6 +424,26 @@ class SecureProxySslHeaderTest(SimpleTestCase):
|
||||
req.META["HTTP_X_FORWARDED_PROTO"] = "https"
|
||||
self.assertIs(req.is_secure(), True)
|
||||
|
||||
@override_settings(SECURE_PROXY_SSL_HEADER=("HTTP_X_FORWARDED_PROTO", "https"))
|
||||
def test_set_with_xheader_leftmost_right(self):
|
||||
req = HttpRequest()
|
||||
req.META["HTTP_X_FORWARDED_PROTO"] = "https, http"
|
||||
self.assertIs(req.is_secure(), True)
|
||||
req.META["HTTP_X_FORWARDED_PROTO"] = "https , http"
|
||||
self.assertIs(req.is_secure(), True)
|
||||
|
||||
@override_settings(SECURE_PROXY_SSL_HEADER=("HTTP_X_FORWARDED_PROTO", "https"))
|
||||
def test_set_with_xheader_leftmost_not_secure(self):
|
||||
req = HttpRequest()
|
||||
req.META["HTTP_X_FORWARDED_PROTO"] = "http, https"
|
||||
self.assertIs(req.is_secure(), False)
|
||||
|
||||
@override_settings(SECURE_PROXY_SSL_HEADER=("HTTP_X_FORWARDED_PROTO", "https"))
|
||||
def test_set_with_xheader_multiple_not_secure(self):
|
||||
req = HttpRequest()
|
||||
req.META["HTTP_X_FORWARDED_PROTO"] = "http ,wrongvalue,http,http"
|
||||
self.assertIs(req.is_secure(), False)
|
||||
|
||||
@override_settings(SECURE_PROXY_SSL_HEADER=("HTTP_X_FORWARDED_PROTO", "https"))
|
||||
def test_xheader_preferred_to_underlying_request(self):
|
||||
class ProxyRequest(HttpRequest):
|
||||
|
Loading…
Reference in New Issue
Block a user