DisallowedHost
Исключение DisallowedHost выбрасывается при обработке входящего HTTP-запроса, если значение заголовка Host не соответствует ни одному из допустимых доменов в настройке ALLOWED_HOSTS. Это критически важная защита от уязвимостей, связанных с подделкой заголовка хоста, которые могут привести к инъекциям паролей, кеш-отравлению и другим атакам. Исключение наследуется от SuspiciousOperation и обрабатывается промежуточным слоем Django.
Синтаксис
from django.core.exceptions import DisallowedHost
# Исключение создается автоматически при несовпадении Host
raise DisallowedHost("Invalid HTTP_HOST header")
Пример
Рассмотрим базовую настройку допустимых хостов в проекте:
# settings.py
ALLOWED_HOSTS = ['example.com', 'www.example.com', '127.0.0.1']
Если Django получит запрос с заголовком Host, отличным от указанных, произойдет исключение:
# Запрос с Host: malicious-site.com
# Django автоматически возбуждает DisallowedHost
from django.core.exceptions import DisallowedHost
try:
# В реальности это происходит в обработчике запроса
raise DisallowedHost("HTTP_HOST header: 'malicious-site.com'")
except DisallowedHost as e:
print(f"Ошибка безопасности: {e}")
Результат выполнения кода:
"Ошибка безопасности: HTTP_HOST header: 'malicious-site.com'"
Пример
Исключение также возникает при запросах без заголовка Host или с некорректным форматом. Обработаем ситуацию с помощью промежуточного слоя:
from django.core.exceptions import DisallowedHost
from django.http import HttpRequest
def process_request(request: HttpRequest):
try:
# Имитация проверки Host в middleware
allowed = ['myapp.com', 'api.myapp.com']
host = request.get_host()
if host not in allowed:
raise DisallowedHost(f"Host '{host}' not allowed")
except DisallowedHost as e:
print(f"Заблокирован запрос: {e}")
return None # В реальности возвращается HTTP 400
# Проверяем с некорректным хостом
req = HttpRequest()
req.META['HTTP_HOST'] = 'fake-domain.net'
process_request(req)
Результат выполнения кода:
"Заблокирован запрос: Host 'fake-domain.net' not allowed"
Пример
Для корректной обработки в продакшене список ALLOWED_HOSTS должен включать все домены, которые обслуживает приложение. Динамическое определение хоста демонстрирует гибкость настройки:
import os
from django.core.exceptions import DisallowedHost
# Динамическое определение разрешенных хостов
ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')
def validate_host(host: str) -> bool:
for allowed in ALLOWED_HOSTS:
if host == allowed or (allowed.startswith('.') and host.endswith(allowed)):
return True
raise DisallowedHost(f"Host '{host}' is not in ALLOWED_HOSTS")
try:
validate_host('sub.example.com') # example.com в ALLOWED_HOSTS
except DisallowedHost as e:
print(f"Исключение: {e}")
Результат выполнения кода:
"Исключение: Host 'sub.example.com' is not in ALLOWED_HOSTS"
Смотрите также
-
исключение
SuspiciousOperation,
базовое исключение для подозрительных операций -
исключение
DisallowedRedirect,
возникает при запрещенном перенаправлении -
исключение
BadRequest,
сигнализирует о некорректном запросе -
исключение
ImproperlyConfigured,
указывает на ошибки в конфигурации Django