mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #33569 -- Added SECURE_PROXY_SSL_HEADER support for list of protocols in the header value.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							d46e158ee2
						
					
				
				
					commit
					1cf60ce601
				
			| @@ -261,7 +261,8 @@ class HttpRequest: | |||||||
|                 ) |                 ) | ||||||
|             header_value = self.META.get(header) |             header_value = self.META.get(header) | ||||||
|             if header_value is not None: |             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() |         return self._get_scheme() | ||||||
|  |  | ||||||
|     def is_secure(self): |     def is_secure(self): | ||||||
|   | |||||||
| @@ -2442,8 +2442,17 @@ required value. For example:: | |||||||
|     SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') |     SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') | ||||||
|  |  | ||||||
| This tells Django to trust the ``X-Forwarded-Proto`` header that comes from our | 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 | proxy and that the request is guaranteed to be secure (i.e., it originally came | ||||||
| be secure (i.e., it originally came in via HTTPS). | 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 | You should *only* set this setting if you control your proxy or have some other | ||||||
| guarantee that it sets/strips this header appropriately. | guarantee that it sets/strips this header appropriately. | ||||||
| @@ -2463,8 +2472,9 @@ available in ``request.META``.) | |||||||
|  |  | ||||||
|     * Your Django app is behind a proxy. |     * Your Django app is behind a proxy. | ||||||
|     * Your proxy strips the ``X-Forwarded-Proto`` header from all incoming |     * Your proxy strips the ``X-Forwarded-Proto`` header from all incoming | ||||||
|       requests. In other words, if end users include that header in their |       requests, even when it contains a comma-separated list of protocols. In | ||||||
|       requests, the proxy will discard it. |       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, |     * Your proxy sets the ``X-Forwarded-Proto`` header and sends it to Django, | ||||||
|       but only for requests that originally come in via HTTPS. |       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 | * The new :setting:`SECRET_KEY_FALLBACKS` setting allows providing a list of | ||||||
|   values for secret key rotation. |   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 | Serialization | ||||||
| ~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -424,6 +424,26 @@ class SecureProxySslHeaderTest(SimpleTestCase): | |||||||
|         req.META["HTTP_X_FORWARDED_PROTO"] = "https" |         req.META["HTTP_X_FORWARDED_PROTO"] = "https" | ||||||
|         self.assertIs(req.is_secure(), True) |         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")) |     @override_settings(SECURE_PROXY_SSL_HEADER=("HTTP_X_FORWARDED_PROTO", "https")) | ||||||
|     def test_xheader_preferred_to_underlying_request(self): |     def test_xheader_preferred_to_underlying_request(self): | ||||||
|         class ProxyRequest(HttpRequest): |         class ProxyRequest(HttpRequest): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user