Сообщения об ошибке¶
Когда вы работаете с публичным сайтом, вам всегда следует отключать параметр DEBUG. Это значительно ускорит работу вашего сервера, а также не позволит злоумышленникам увидеть детали вашего приложения, которые могут быть раскрыты страницами с ошибками.
Однако запуск с DEBUG установленным на False означает, что вы никогда не увидите ошибок, сгенерированных вашим сайтом — вместо этого все будут видеть ваши общедоступные страницы ошибок. Вам необходимо отслеживать ошибки, которые происходят на развернутых сайтах, поэтому Django можно настроить для создания отчетов с подробностями об этих ошибках.
Отчеты по электронной почте¶
Ошибки сервера¶
Когда DEBUG имеет значение False, Django будет отправлять электронные письма пользователям, указанным в настройке ADMINS, всякий раз, когда ваш код вызывает необработанное исключение и приводит к внутренней ошибке сервера (строго говоря, для любого ответа с кодом состояния HTTP 500 или выше). Это дает администраторам немедленное уведомление о любых ошибках. ADMINS получит описание ошибки, полную трассировку Python и подробности о HTTP-запросе, вызвавшем ошибку.
Примечание
Для отправки электронной почты Django требуется несколько настроек, сообщающих ему, как подключаться к вашему почтовому серверу. Как минимум, вам нужно будет указать EMAIL_HOST и, возможно, EMAIL_HOST_USER и EMAIL_HOST_PASSWORD, хотя могут потребоваться и другие настройки в зависимости от конфигурации вашего почтового сервера. Ознакомьтесь с документацией по настройкам Django для получения полного списка настроек, связанных с электронной почтой.
По умолчанию Django отправляет почту с root@localhost. Однако некоторые почтовые провайдеры отклоняют всю почту с этого адреса. Чтобы использовать другой адрес отправителя, измените настройку SERVER_EMAIL.
Чтобы активировать это поведение, укажите адреса электронной почты получателей в настройке ADMINS.
См.также
Письма об ошибках сервера отправляются с использованием фреймворка logging, поэтому вы можете настроить это поведение, настроив конфигурацию ведения журнала.
Ошибки 404¶
Django также можно настроить на отправку сообщений об ошибках, связанных с битыми ссылками (ошибки 404 «page not found»). Django отправляет сообщения об ошибках 404, когда:
DEBUGустановлена вFalseВ настройках
MIDDLEWAREсодержитсяdjango.middleware.common.BrokenLinkEmailsMiddleware.
При выполнении этих условий, Django вышлет отчёт пользователям, указанным в секции MANAGERS, если код выдаст ошибку 404 и запрос содержит «referer». Это не относится к ошибке 404 на запрос, который не содержит «referer» – как правило, в этом случае ошибка связана с тем, что пользователь вводит неверный адрес, или Web-боты запрашивают неверный адрес. Также игнорируются 404, если запрос содержит «referer» равный запрошенному URL, они обычно так же вызваны Web-ботами.
Примечание
BrokenLinkEmailsMiddleware must appear
before other middleware that intercepts 404 errors, such as
LocaleMiddleware or
FlatpageFallbackMiddleware.
Put it towards the top of your MIDDLEWARE setting.
Вы можете отключить отчёты о 404 ошибке, настроив IGNORABLE_404_URLS. Это должен быть список со скомпилированными объектами регулярных выражений. Например:
import re
IGNORABLE_404_URLS = [
re.compile(r'\.(php|cgi)$'),
re.compile(r'^/phpmyadmin/'),
]
В этом примере уведомление об ошибке 404 не будет присылаться, если URL страницы заканчивается на .php или .cgi. Также в исключения добавлена директория /phpmyadmin/.
В приведённом ниже примере показано как добавить в исключения некоторые URL, которые часто запрашиваются браузером и поисковыми роботами:
import re
IGNORABLE_404_URLS = [
re.compile(r'^/apple-touch-icon.*\.png$'),
re.compile(r'^/favicon\.ico$'),
re.compile(r'^/robots\.txt$'),
]
(Заметьте, что это регулярные выражения, и нужно ставить обратный слэш, чтобы экранировать значения.)
Если хочется изменить дальнейшее поведение django.middleware.common.BrokenLinkEmailsMiddleware (изначально игнорирует запросы от поисковых роботов), необходимо переопределить методы в его подклассах.
См.также
При отправке 404 ошибки задействуется логгирование. Изначально записи игнорируются, но могут быть использованы для отправки отчётов при записи с помощью обработчика и настройки логгирования.
Фильтрация сообщений об ошибках¶
Предупреждение
Фильтрация конфиденциальной информации – это сложная задача, и нет никакой гарантии, что она не появится в отчете об ошибке. Поэтому отчеты об ошибках должны быть доступны только доверенным членам команды и не передаваться в открытом виде через интернет(например по почте).
Фильтрация конфиденциальной информации¶
Отчёты об ошибках весьма полезны для отладки, поэтому лучше записывать как можно больше соответствующей информации о различных инцидентах. Например, изначально Django сохраняет полную трассировочную информацию о вызванных исключениях, каждую локальную переменную кадра трассировки и атрибуты класса HttpRequest.
Однако, некоторая информация может быть конфиденциальной и совершенно не подходит для отслеживания, к таким моментам можно отнести пароль пользователя или номер кредитной карты. Django предлагает несколько декораторов для контроля информации, которая должна быть отфильтрована при отправке отчётов на сервере в продакшене (то есть там, где DEBUG установлен в False): sensitive_variables() и sensitive_post_parameters().
- sensitive_variables(*variables)¶
Если функция (или представление регулярного выражения) в вашем коде использует локальные переменные, содержащие конфиденциальную информацию, вы можете предотвратить появление этих переменных при отправке отчётов при помощи декоратора
sensitive_variables:from django.views.decorators.debug import sensitive_variables @sensitive_variables('user', 'pw', 'cc') def process_info(user): pw = user.pass_word cc = user.credit_card_number name = user.name ...
В примере выше значения переменных
user,pwиccбудут скрыты и заменены на символы звёздочки (**********) в отчёте, в то время как значение переменнойnameбудет открытым.Систематическое скрытие всех локальных переменных функции из журнала ошибок (error logs) не требует никаких аргументов декоратора
sensitive_variables:@sensitive_variables() def my_function(): ...
При использовании нескольких декораторов
Если переменная, значение которой вы хотите скрыть, также является аргументом функции (как „
user“ в приведённом примере), и декорируемая функция имеет множество декораторов, убедитесь, что@sensitive_variablesнаходится на самом верху цепочки. Это позволит также скрыть аргументы функции, взаимодействующие с другими декораторами:@sensitive_variables('user', 'pw', 'cc') @some_decorator @another_decorator def process_info(user): ...
- sensitive_post_parameters(*parameters)¶
Если одно из представлений объекта
HttpRequestс атрибутомPOST parametersподтверждает содержание конфиденциальной информации, вы можете предотвратить включение этих данных в отчёт, используя декораторsensitive_post_parametersfrom django.views.decorators.debug import sensitive_post_parameters @sensitive_post_parameters('pass_word', 'credit_card_number') def record_user_profile(request): UserProfile.create( user=request.user, password=request.POST['pass_word'], credit_card=request.POST['credit_card_number'], name=request.POST['name'], ) ...
В данном выше примере значения
pass_wordиcredit_card_numberв POST запросе будут скрыты и заменены звёздочками (**********) при представлении запроса в отчёте об ошибках, в то время как параметрnameбудет открытым.Чтобы спрятать все POST параметры из журнала ошибок (error logs), не передавайте аргументы декоратору
sensitive_post_parameters@sensitive_post_parameters() def my_view(request): ...
Все POST параметры систематически фильтруются в отчёте об ошибках в представлении
django.contrib.auth.views(login,password_reset_confirm,password_change, иadd_viewиuser_change_passwordв системе аутентификации) для предотвращения утечки конфиденциальной информации, такой как пароли пользователей.
Настройка отчета об ошибке¶
Декораторы sensitive_variables() и sensitive_post_parameters() отмечают небезопасные аргументы и POST аргументы объекта HttpRequest, которые передаются в функцию. При формировании отчета об ошибке эти данные фильтруются. Фильтрация выполняется классом django.views.debug.SafeExceptionReporterFilter. Этот класс заменит отмеченные декоратором данные «звездочками» (**********) при формировании отчета. Вы можете создать собственный класс фильтрации и указать его в настройке DEFAULT_EXCEPTION_REPORTER_FILTER:
DEFAULT_EXCEPTION_REPORTER_FILTER = 'path.to.your.CustomExceptionReporterFilter'
Также можно указать класс фильтрации для конкретного HttpRequest определив атрибут exception_reporter_filter:
def my_view(request):
if request.user.is_authenticated:
request.exception_reporter_filter = CustomExceptionReporterFilter()
...
Ваш класс фильтрации должен наследоваться от django.views.debug.SafeExceptionReporterFilter и может переопределить следующие методы:
- class SafeExceptionReporterFilter¶
- cleansed_substitute¶
- New in Django 3.1.
Строковое значение, которым следует заменить конфиденциальное значение. По умолчанию оно заменяет значения конфиденциальных переменных на звездочки (
**********).
- New in Django 3.1.
Скомпилированный объект регулярного выражения, используемый для сопоставления настроек и
request.Значения METAсчитаются конфиденциальными. По умолчанию эквивалентно:import re re.compile(r'API|TOKEN|KEY|SECRET|PASS|SIGNATURE', flags=re.IGNORECASE)
- is_active(request)¶
Возвращает
Trueдля активации фильтрации вget_post_parameters()иget_traceback_frame_variables(). По умолчанию фильтр активен, еслиDEBUGравноFalse. Обратите внимание, что конфиденциальные значенияrequest.METAвсегда фильтруются вместе со значениями настроек конфиденциальности, как описано в документацииDEBUG.
- get_post_parameters(request)¶
Возвращает отфильтрованный словарь параметров POST. Конфиденциальные значения заменяются на
cleansed_substitute.
- get_traceback_frame_variables(request, tb_frame)¶
Возвращает отфильтрованный словарь локальных переменных для заданного кадра трассировки. Конфиденциальные значения заменяются на
cleansed_substitute.
Если вам необходимо настроить отчеты об ошибках помимо фильтрации, вы можете указать класс специального отчета об ошибках, определив :setting:параметр DEFAULT_EXCEPTION_REPORTER:
DEFAULT_EXCEPTION_REPORTER = 'path.to.your.CustomExceptionReporter'
Репортер исключений отвечает за компиляцию данных отчета об исключениях и форматирование их в виде текста или HTML соответствующим образом. (Репортер исключений использует DEFAULT_EXCEPTION_REPORTER_FILTER при подготовке данных отчета об исключениях.)
Ваш пользовательский класс репортера должен наследоваться от django.views.debug. ExceptionReporter.
- class ExceptionReporter¶
- get_traceback_data()¶
Вернуть словарь, содержащий трассировочную информацию.
Это основная точка расширения для настройки отчетов об исключениях, например:
from django.views.debug import ExceptionReporter class CustomExceptionReporter(ExceptionReporter): def get_traceback_data(self): data = super().get_traceback_data() # ... remove/add something here ... return data
- get_traceback_html()¶
Вернуть HTML-версию отчета об исключении.
Используется для HTML-версии отладочной страницы ошибки HTTP 500.
- get_traceback_text()¶
Вернуть текстовую версию отчета об исключении.
Используется для текстовой версии страницы отладки 500 HTTP-ошибки и отчетов по электронной почте.
Как и в случае с классом фильтра, вы можете контролировать, какой класс отчета об исключениях использовать в любом заданном представлении, установив атрибут HttpRequest exception_reporter_class:
def my_view(request):
if request.user.is_authenticated:
request.exception_reporter_class = CustomExceptionReporter()
...
См.также
Вы также можете настроить пользовательские отчеты об ошибках, написав пользовательский фрагмент exception middleware. Если вы пишете пользовательскую обработку ошибок, хорошей идеей будет эмулировать встроенную обработку ошибок Django и сообщать/регистрировать ошибки только в том случае, если DEBUG имеет значение False.