Промежуточный слой (Middleware)¶
Этот раздел описывает промежуточные слои, которые предоставляет Django. Как использовать и создавать свои промежуточные слои, смотрите соответствующий раздел.
Доступные промежуточные слои¶
Кэширующий промежуточный слой¶
- class UpdateCacheMiddleware¶
- class FetchFromCacheMiddleware¶
Активирует кэширование для всего сайта. При этом все страницы, которые генерируются Django, будут закэшированы на время, указанное в настройке CACHE_MIDDLEWARE_SECONDS. Смотрите раздел о кэшировании.
«Common» промежуточный слой¶
- class CommonMiddleware¶
- response_redirect_class¶
По умолчанию
HttpResponsePermanentRedirect. Можете создать класс наследникCommonMiddlewareи переопределить класс ответа, который используется для перенаправления.
Добавляет несколько полезностей для перфекционистов:
Ограничивает доступ для клиентов, которые указанны в настройке
DISALLOWED_USER_AGENTS. Настройка должна содержать список скомпилированных регулярных выражений.Меняет URL в соответствии с настройками
APPEND_SLASHиPREPEND_WWW.Если
APPEND_SLASHравнаTrueи вызванный URL не оканчивается на слеш, и он не найден в URLconf, создается новый URL путем добавления слеша в конец. Если новый URL найден в URLconf, Django отправляет перенаправление на этот URL. Иначе начальный URL обрабатывается как обычно.Например,
foo.com/barбудет перенаправлен наfoo.com/bar/, если нет URL-шаблона дляfoo.com/bar, но есть дляfoo.com/bar/.Если
PREPEND_WWWравнаTrue, URL-ы без «www.» будут перенаправлены на URL с добавлением «www.»Обе эти настройки предназначены для нормализации URL-ов. Философия такая – URL должен быть уникальным и единым. Технически URL
foo.com/barотличается отfoo.com/bar/– поисковик проиндексирует их как отдельные URL-ы – поэтому хорошей практикой является нормализация URL-ов.При необходимости отдельные представления могут быть исключены из поведения
APPEND_SLASHс помощью декоратораno_append_slash():from django.views.decorators.common import no_append_slash @no_append_slash def sensitive_fbv(request, *args, **kwargs): """View to be excluded from APPEND_SLASH.""" return HttpResponse()
Устанавливает заголовок Content-Length для непотоковых ответов.
- class BrokenLinkEmailsMiddleware¶
Отсылает уведомления о сломанных ссылках на
MANAGERS(смотрите Как управлять сообщениями об ошибках).
GZip промежуточный слой¶
- class GZipMiddleware¶
- max_random_bytes¶
По умолчанию — 100. Подкласс GZipMiddleware и переопределите атрибут, чтобы изменить максимальное количество случайных байтов, которые включаются в сжатые ответы.
Примечание
Исследователи безопасности обнаружили, что когда на веб-сайте используются методы сжатия (включая GZipMiddleware), сайт может стать уязвимым для ряда возможных атак.
Для смягчения атак Django реализует технику под названием Heal The Breach (HTB). Он добавляет до 100 байт (см. max_random_bytes) случайных байтов к каждому ответу, чтобы сделать атаки менее эффективными.
Более подробную информацию см. в документе BREACH paper (PDF), breachattack.com и _ в документе `_ Heal The Breach (HTB).
Сжимает ответ для браузеров, которые поддерживают GZip (все современные браузеры).
Этот промежуточный слой должен находится перед любым другим промежуточный слоем, который читает или пишет содержимое ответа, чтобы сжатие происходило в самом конце.
Содержимое ответа НЕ будет сжато при следующих условиях:
Содержимое ответа меньше 200 байтов.
Ответ уже содержит заголовок
Content-Encoding.Браузер не отослал в запросе заголовок
Accept-Encoding, который содержитgzip.
Если ответ имеет заголовок ETag, ETag становится слабым, чтобы соответствовать RFC 9110 Section 8.8.1.
Вы можете применить сжатие GZip к отдельным представлениям, используя декоратор gzip_page().
Промежуточный слой для обработки условных GET-запросов¶
- class ConditionalGetMiddleware¶
Обрабатывает условные GET операции. Если ответ содержит заголовки ETag или Last-Modified, и запрос содержит If-None-Match или If-Modified-Since, ответ заменяется на HttpResponseNotModified.
Вы можете обрабатывать условные операции GET с отдельными представлениями, используя декоратор conditional_page().
Промежуточный слой локализации¶
- class LocaleMiddleware¶
- response_redirect_class¶
По умолчанию
HttpResponseRedirect. Можете создать класс наследникLocaleMiddlewareи переопределить класс ответа, который используется для перенаправления.
Выполняет выбор текущего языка на основе данных из запроса. Меняет содержимое для каждого пользователя отдельно. Смотрите раздел об интернационализации.
Промежуточный слой сообщений¶
- class MessageMiddleware¶
Добавляет поддержку сообщений на основе кук или сессии. Смотрите раздел о сообщениях.
Промежуточный слой безопасности¶
Предупреждение
Если позволяет ситуация с развертыванием, обычно рекомендуется, чтобы ваш интерфейсный веб-сервер выполнял функции, предоставляемые SecurityMiddleware. Таким образом, если есть запросы, которые не обслуживаются Django (например, статические медиафайлы или файлы, загруженные пользователем), они будут иметь ту же защиту, что и запросы к вашему приложению Django.
- class SecurityMiddleware¶
django.middleware.security.SecurityMiddleware предоставляет ряд проверок безопасности при обработке запроса/ответа. Каждая из них может быть выключена/включена насройкой.
HTTP Strict Transport Security¶
Для сайтов, которые должны быть доступны только по HTTPS, вы можете указать современным браузерам не подключаться к вашему домену по небезопасному подключению (в течении определенного времени), установив заголовок «Strict-Transport-Security». Это уменьшает подверженность MITM атакам.
SecurityMiddleware будет устанавливать этот заголовок для всех HTTPS ответов, если вы укажите в настройке SECURE_HSTS_SECONDS не нулевое значение.
При включении HSTS рекомендуется сначала использовать небольшое значение для тестирования, например, SECURE_HSTS_SECONDS = 3600 на один час. Каждый раз, когда веб-браузер видит заголовок HSTS с вашего сайта, он отказывается обмениваться незащищенным соединением (с использованием HTTP) с вашим доменом в течение определенного периода времени. Как только вы подтвердите, что все ресурсы на вашем сайте обслуживаются безопасно (т. е. HSTS ничего не сломал), рекомендуется увеличить это значение, чтобы нечастые посетители были защищены (обычно 31536000 секунд, т. е. 1 год).
Если вы установите True еще и в SECURE_HSTS_INCLUDE_SUBDOMAINS, SecurityMiddleware``добавит тег ``includeSubDomains к заголовку Strict-Transport-Security. Рекомендуем включить эту настройку (убедитесь, что все поддомены работают по HTTPS), иначе ваш сайт может быть уязвим через небезопасное подключение к поддомену.
Если вы хотите добавить свой сайт в список предварительной загрузки браузера, установите для параметра SECURE_HSTS_PRELOAD значение True. При этом директива preload добавляется к заголовку Strict-Transport-Security.
Предупреждение
HSTS применяется ко всему домену, а не только URL, который вернул ответ с заголовком. Поэтому вам следует использовать его только, если весь домен доступен через HTTPS.
Браузеры, которые поддерживают заголовки HSTS, не позволят пользователям игнорировать предупреждение и подключиться к сайту с устаревшим, самостоятельно подписанным, или неправильным SSL сертификатом. Если вы используете HSTS, убедитесь, что с вашими сертификатами все впорядке!
Примечание
Если ваш сервер находится за балансировщиком нагрузки, или прокси, и заголовок Strict-Transport-Security не добавляется к ответам, это может быть вызвано тем, что Django не определяет, что используется защищенное подключение. Возможно вам следует указать настройку SECURE_PROXY_SSL_HEADER.
Политика рефералов¶
Браузеры используют «заголовок Referer»__ как способ отправки на сайт информации о том, как на него попали пользователи. Когда пользователь нажимает ссылку, браузер отправляет полный URL-адрес ссылающейся страницы в качестве реферера. Хотя это может быть полезно для некоторых целей (например, для выяснения того, кто ссылается на ваш сайт), это также может вызвать проблемы конфиденциальности, сообщая одному сайту, что пользователь посещал другой сайт.
Некоторые браузеры имеют возможность принимать подсказки о том, следует ли отправлять HTTP-заголовок «Referer», когда пользователь нажимает ссылку; эта подсказка предоставляется через `заголовок Referrer-Policy`__. Этот заголовок может предложить браузерам любое из трех вариантов поведения:
Полный URL-адрес: отправьте весь URL-адрес в заголовке «Referer». Например, если пользователь посещает https://example.com/page.html, заголовок Referer будет содержать https://example.com/page.html.
Только источник: отправляйте только «источник» в реферере. Источник состоит из схемы, хоста и (необязательно) номера порта. Например, если пользователь посещает https://example.com/page.html, источником будет https://example.com/.
Нет реферера: вообще не отправлять заголовок «Referer».
Существует два типа условий, на которые этот заголовок может указать браузеру:
Одно и то же происхождение или перекрестное происхождение: ссылка с «https://example.com/1.html» на «https://example.com/2.html» имеет одинаковое происхождение. Ссылка с https://example.com/page.html на https://not.example.com/page.html является перекрестной.
Понижение версии протокола: понижение версии происходит, если страница, содержащая ссылку, обслуживается через HTTPS, но страница, на которую имеется ссылка, не обслуживается через HTTPS.
Предупреждение
Когда ваш сайт обслуживается через HTTPS, Система защиты CSRF Django требует присутствия заголовка Referer, поэтому полное отключение заголовка Referer будет мешать защите CSRF. Чтобы получить большую часть преимуществ от отключения заголовков Referer, сохраняя при этом защиту CSRF, рассмотрите возможность включения только рефереров того же происхождения.
SecurityMiddleware может установить для вас заголовок Referrer-Policy на основе параметра SECURE_REFERRER_POLICY (обратите внимание на написание: браузеры отправляют заголовок Referer, когда пользователь нажимает ссылку, но заголовок, инструктирующий браузер, следует ли это делать, пишется Referrer-Policy). Допустимые значения для этого параметра:
без реферераУказывает браузеру не отправлять реферер для ссылок, по которым нажимают на этом сайте.
без реферера при понижении версииУказывает браузеру отправлять полный URL-адрес в качестве реферера, но только в том случае, если не происходит перехода на более раннюю версию протокола.
происхождениеУказывает браузеру отправлять в качестве реферера только источник, а не полный URL-адрес.
происхождение-когда-перекрестное происхождениеУказывает браузеру отправлять полный URL-адрес в качестве реферера для ссылок с одним и тем же источником и только источник для ссылок с перекрестным источником.
same-origin Указывает браузеру отправлять полный URL-адрес, но только для ссылок того же происхождения. Для ссылок с перекрестным происхождением реферер не будет отправлен.
strict-origin Указывает браузеру отправлять только источник, а не полный URL-адрес, и не отправлять реферер при переходе на более раннюю версию протокола.
строгое происхождение при перекрестном происхожденииУказывает браузеру отправлять полный URL-адрес, если ссылка имеет одно и то же происхождение и не происходит перехода на более раннюю версию протокола; отправлять только источник, если ссылка является перекрестной и не происходит перехода на более раннюю версию протокола; и отсутствие реферера при переходе на более раннюю версию протокола.
небезопасный-urlУказывает браузеру всегда отправлять полный URL-адрес в качестве источника перехода.
Неизвестные значения политики
Если значение политики «неизвестно»__ пользовательскому агенту, можно указать несколько значений политики, чтобы обеспечить запасной вариант. Последнее заданное значение, которое понятно, имеет приоритет. Для поддержки этого можно использовать повторяемую строку или строку, разделенную запятыми, с SECURE_REFERRER_POLICY.
Политика открытия перекрестного происхождения¶
Некоторые браузеры имеют возможность изолировать окна верхнего уровня от других документов, помещая их в отдельную группу контекста просмотра на основе значения заголовка «Cross-Origin Opener Policy»__ (COOP). Если документ, изолированный таким образом, открывает всплывающее окно с разными источниками, свойство всплывающего окна window.opener будет иметь значение null. Изоляция окон с помощью COOP — это глубокая защита от атак из разных источников, особенно от таких, как Spectre, которые допускают утечку данных, загруженных в общий контекст просмотра.
SecurityMiddleware может установить для вас заголовок Cross-Origin-Opener-Policy на основе настройки SECURE_CROSS_ORIGIN_OPENER_POLICY. Допустимые значения для этого параметра:
того же происхожденияИзолирует контекст просмотра исключительно для документов того же происхождения. Документы из разных источников не загружаются в одном и том же контексте просмотра. Это вариант по умолчанию и наиболее безопасный.
тот же источник-разрешить-всплывающие окнаИзолирует контекст просмотра от документов того же происхождения или тех, которые либо не устанавливают COOP, либо отказываются от изоляции, устанавливая для COOP значение
unsafe-none.небезопасно-нетПозволяет добавлять документ в контекстную группу просмотра его открывающего устройства, если только само открывающее средство не имеет COOP
same-originили``same-origin-allow-popups``.
X-Content-Type-Options: nosniff¶
Некоторые браузеры пытаются угадать тип содержимого(content type) полученных файлов, подменяя заголовок Content-Type. В то время, как такой подход помогает правильно отображать сайты с неправильно настроенных серверов, он может быть и уязвимостью.
Если ваш сайт позволяет пользователям загружать файлы, взломщик может загрузить специальный файл, который будет интерпретирован браузером как HTML или Javascript.
Чтобы запретить браузеру угадывать тип контента и заставить его всегда использовать тип, указанный в заголовке Content-Type, вы можете передать заголовок X-Content-Type-Options: nosniff`__. SecurityMiddleware сделает это для всех ответов, если параметр SECURE_CONTENT_TYPE_NOSNIFF имеет значение True.
Обратите внимание: в большинстве ситуаций развертывания, когда Django не участвует в обслуживании загруженных пользователем файлов, этот параметр вам не поможет. Например, если ваш MEDIA_URL обслуживается непосредственно вашим интерфейсным веб-сервером (nginx, Apache и т. д.), тогда вам нужно установить этот заголовок там. С другой стороны, если вы используете Django для чего-то вроде запроса авторизации для загрузки файлов и не можете установить заголовок с помощью веб-сервера, этот параметр будет полезен.
SSL редирект¶
Если ваш сайт доступен по HTTP и HTTPS, большинство пользователей будут заходить по незащищенному подключению по умолчанию. Вам следует перенапралять их с HTTP на HTTPS.
Если установить True в SECURE_SSL_REDIRECT, SecurityMiddleware будет перманентно (HTTP 301) перенаправлять все HTTP запросы на HTTPS.
Примечание
Для повышения производительности лучше делать эти перенаправления не в Django, а на балансере нагрузки или прокси, таком как nginx. SECURE_SSL_REDIRECT следует использовать для разработки, чтобы не усложнять локальное окружение.
Если указать значение в настройке SECURE_SSL_HOST, все перенаправления будут выполняться на указанный хост, а не хост из запроса.
Если на сайте есть страницы, которые должны быть доступны по HTTP без перенаправления на HTTPS, вы можете указать в настройке SECURE_REDIRECT_EXEMPT регулярные выражение, которым удовлетворяют необходимые URL-ы.
Примечание
Если ваш сервер находится за балансировщиком нагрузки или прокси, Django может не определяет, что используется защищенное подключение. Возможно вам следует указать настройку SECURE_PROXY_SSL_HEADER.
Промежуточный слой сессии¶
- class SessionMiddleware¶
Включает поддержку сессии. Смотрите раздел о сессии.
Middleware для сайтов¶
- class CurrentSiteMiddleware¶
Добавляет атрибут site, который указывает текущий сайт для каждого объекта HttpRequest. Смотрите раздел о поддержке нескольких сайтов.
Промежуточный слой авторизации¶
- class AuthenticationMiddleware¶
Добавляет атрибут user, представляющий пользователя, вошедшего в систему в данный момент, к каждому входящему объекту HttpRequest. См. Аутентификация в веб-запросах.
- class LoginRequiredMiddleware¶
Создайте подкласс промежуточного программного обеспечения и переопределите следующие атрибуты и методы, чтобы настроить поведение для неаутентифицированных запросов.
- redirect_field_name¶
По умолчанию
"следующий".
- get_login_url()¶
Возвращает URL-адрес, на который будут перенаправлены неаутентифицированные запросы. Этим результатом является либо
login_url, установленный в декоратореlogin_required()(если неNone), либоsettings.LOGIN_URL.
- get_redirect_field_name()¶
Возвращает имя параметра запроса, содержащего URL-адрес, на который пользователь должен быть перенаправлен после успешного входа в систему. Этим результатом является либо
redirect_field_name, установленное в декоратореlogin_required()(если неNone), либоredirect_field_name. Если возвращается None, параметр запроса не будет добавлен.
Перенаправляет все неаутентифицированные запросы на страницу входа, за исключением просмотров, исключенных с помощью login_not_required(). По умолчанию страница входа имеет вид settings.LOGIN_URL, но ее можно настроить.
Включите это промежуточное программное обеспечение, добавив его в настройку MIDDLEWARE after AuthenticationMiddleware:
MIDDLEWARE = [
"...",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.auth.middleware.LoginRequiredMiddleware",
"...",
]
Сделайте представление общедоступным, разрешив запросы без аутентификации, с помощью login_not_required(). Например:
from django.contrib.auth.decorators import login_not_required
@login_not_required
def contact_us(request): ...
Настройте URL-адрес входа или имя поля для аутентифицированных представлений с помощью декоратора login_required(), чтобы установить login_url или redirect_field_name соответственно. Например:
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import View
@login_required(login_url="/books/login/", redirect_field_name="redirect_to")
def book_dashboard(request): ...
@method_decorator(
login_required(login_url="/books/login/", redirect_field_name="redirect_to"),
name="dispatch",
)
class BookMetrics(View):
pass
Убедитесь, что для просмотра входа не требуется вход в систему.
Чтобы предотвратить бесконечные перенаправления, убедитесь, что у вас включены неаутентифицированные запросы к вашему представлению входа в систему.
- class RemoteUserMiddleware¶
Промежуточное программное обеспечение для использования веб-сервера обеспечивает аутентификацию. Подробности использования см. в Аутентификация при помощи REMOTE_USER.
- class PersistentRemoteUserMiddleware¶
Промежуточное ПО для использования веб-сервера обеспечивало аутентификацию, если она включена только на странице входа в систему. Подробности использования см. в Использование REMOTE_USER только на странице авторизации.
Промежуточный слой для CSRF защиты¶
- class CsrfViewMiddleware¶
Включает CSRF защиту, добавляя скрытое поле в POST формы и проверяя значение при запросе. Смотрите раздел о Cross Site Request Forgery защите.
Вы можете добавить защиту от подделки межсайтовых запросов к отдельным представлениям, используя декоратор csrf_protect().
Промежуточный слой X-Frame-Options¶
- class XFrameOptionsMiddleware¶
Добавляет простую защиту от «clickjacking», используя заголовок X-Frame-Options.
Промежуточное программное обеспечение политики безопасности контента¶
- class ContentSecurityPolicyMiddleware¶
Добавляет поддержку политики безопасности контента (CSP), которая помогает снизить риски, такие как межсайтовый скриптинг (XSS) и атаки путем внедрения данных, путем контроля источников контента, который может быть загружен в браузер. Подробную информацию о настройке политик смотрите в документации Обзор.
Это промежуточное программное обеспечение устанавливает следующие заголовки ответа в зависимости от доступных настроек:
Content-Security-Policy, на основе:setting:SECURE_CSP.Content-Security-Policy-Report-Only, на основе:setting:SECURE_CSP_REPORT_ONLY.
Порядок промежуточных слоёв¶
Несколько советов о порядке промежуточных слоёв Django:
-
Должен следовать в начале списка промежуточных слоев, если вы используете SSL перенаправление, чтобы избежать обработки небезопасного запроса другими промежуточными слоями.
-
Добавлять перед промежуточными слоями, которые могут изменить заголовок
Vary(SessionMiddleware,GZipMiddleware,LocaleMiddleware). -
Добавлять перед промежуточными слоями, которые могут изменять или читать тело ответа.
После
UpdateCacheMiddleware: изменяет заголовокVary. -
Перед любым промежуточным программным обеспечением, которое может вызвать исключение для запуска представления ошибок (например,
PermissionDenied), если вы используетеCSRF_USE_SESSIONS.После
UpdateCacheMiddleware: изменяет заголовокVary. -
Перед любым промежуточным слоем, который может изменять ответ (вычисляет
ETags).После
GZipMiddleware, чтобы заголовокETagне вычислялся для сжатого ответа. -
Следует одним из первых, после
SessionMiddleware(использует сессию) иCacheMiddleware(изменяет заголовокVary). -
Перед любым промежуточным программным обеспечением, которое может изменить ответ (оно устанавливает заголовок Content-Length). Промежуточное программное обеспечение, которое появляется перед CommonMiddleware и изменяет ответ, должно сбросить Content-Length.
Ближе к верху: выполняет перенаправление при
APPEND_SLASHилиPREPEND_WWWравномTrue.После
SessionMiddleware: использует сессию. -
Перед любым промежуточным слоем, который предполагает, что CSRF защита уже выполнена.
До
RemoteUserMiddlewareили любого другого промежуточного программного обеспечения аутентификации, которое может выполнять вход в систему и, следовательно, менять токен CSRF перед вызовом цепочки промежуточного программного обеспечения.После
SessionMiddleware: использует сессию. -
После
SessionMiddleware: использует сессию. -
После
AuthenticationMiddleware: использует объект пользователя. -
После
SessionMiddleware: может использовать сессию для хранения данных. -
После любого промежуточного слоя, который может изменить заголовок
Vary: его значение используется для генерации ключа в кеше. ContentSecurityPolicyMiddlewareМожет быть размещен внизу, но убедитесь, что все промежуточное программное обеспечение, которое обращается к csp_nonce, расположено после него, чтобы nonce был правильно включен в заголовок ответа.
-
Должен быть в низу.
-
Должен быть в низу.