當(dāng)你運行一個公開站點時,你應(yīng)該始終關(guān)閉DEBUG
設(shè)置。這會使你的服務(wù)器運行得更快,也會防止惡意用戶看到由錯誤頁面展示的一些應(yīng)用細節(jié)。
但是,運行在 DEBUG
為False
的情況下,你不會看到你的站點所生成的錯誤 -- 每個人都只能看到公開的錯誤頁面。你需要跟蹤部署的站點上的錯誤,所以可以配置Django來生成帶有錯誤細節(jié)的報告。
DEBUG
為 False
的時候,無論什么時候代碼產(chǎn)生了未處理的異常,并且出現(xiàn)了服務(wù)器內(nèi)部錯誤(HTTP狀態(tài)碼 500),Django 都會給ADMINS
設(shè)置中的用戶發(fā)送郵件。 這會向管理員提供任何錯誤的及時通知。 ADMINS
會得到一份錯誤的描述,完整的Python traceback,以及HTTP請求和導(dǎo)致錯誤的詳細信息。
注意
為了發(fā)送郵件,DJango需要一些設(shè)置來告訴它如何連接到郵件服務(wù)器。最起碼,你需要指定 EMAIL_HOST
,可能需要 EMAIL_HOST_USER
和EMAIL_HOST_PASSWORD
,盡管所需的其他設(shè)置可能也依賴于你的郵件服務(wù)器的配置。郵件相關(guān)設(shè)置的完整列表請見 Django設(shè)置文檔。
Django通常從root@localhost發(fā)送郵件。但是一些郵件提供商會拒收所有來自這個地址的郵件。修改SERVER_EMAIL
設(shè)置可以使用不同的發(fā)信人地址。
將收信人的郵箱地址放入ADMINS
設(shè)置中來激活這一行為。
另見
服務(wù)器錯誤郵件使用日志框架來發(fā)送,所以你可以通過 自定義你的日志配置自定義這一行為。
也可以配置Django來發(fā)送關(guān)于死鏈的郵件(404"找不到頁面"錯誤)。Django在以下情況發(fā)送404錯誤的郵件:
DEBUG
為 False
;MIDDLEWARE_CLASSES
設(shè)置含有 django.middleware.common.BrokenLinkEmailsMiddleware
。如果符合這些條件,無論什么時候你的代碼產(chǎn)生404錯誤,并且請求帶有referer, Django 都會給MANAGERS
中的用戶發(fā)送郵件。 (It doesn’t bother to email for 404s that don’t have a referer – those are usually just people typing in broken URLs or broken Web ‘bots).
注意
BrokenLinkEmailsMiddleware
必須出現(xiàn)在其它攔截404錯誤的中間件之前,比如 LocaleMiddleware
或者 FlatpageFallbackMiddleware
。把它放在你的MIDDLEWARE_CLASSES
設(shè)置的最上面。
你可以通過調(diào)整IGNORABLE_404_URLS
設(shè)置,告訴Django停止報告特定的404錯誤。它應(yīng)該為一個元組,含有編譯后的正則表達式對象。例如:
import re
IGNORABLE_404_URLS = (
re.compile(r'\.(php|cgi)$'),
re.compile(r'^/phpmyadmin/'),
)
在這個例子中,任何以.php
或者.cgi
結(jié)尾URL的404錯誤都_不會_報告。任何以/phpmyadmin/
開頭的URL也不會。
下面的例子展示了如何排除一些瀏覽器或爬蟲經(jīng)常請求的常用URL:
import re
IGNORABLE_404_URLS = (
re.compile(r'^/apple-touch-icon.*\.png$'),
re.compile(r'^/favicon\.ico$'),
re.compile(r'^/robots\.txt$'),
)
(要注意這些是正則表達式,所以需要在句號前面添加反斜線來對它轉(zhuǎn)義。)
如果你打算進一步自定義django.middleware.common.BrokenLinkEmailsMiddleware
的行為(比如忽略來自web爬蟲的請求),你應(yīng)該繼承它并覆寫它的方法。
另見
404錯誤使用日志框架來記錄。通常,日志記錄會被忽略,但是你可以通過編寫合適的處理器和配置日志,將它們用于錯誤報告。
錯誤報告對錯誤的調(diào)試及其有用,所以對于這些錯誤,通常它會盡可能多的記錄下相關(guān)信息。例如,通常DJango會為產(chǎn)生的異常記錄完整的traceback,traceback 幀的每個局部變量,以及HttpRequest
的屬性。
然而,有時特定的消息類型十分敏感,并不適合跟蹤消息,比如用戶的密碼或者信用卡卡號。所以Django提供一套函數(shù)裝飾器,來幫助你控制需要在生產(chǎn)環(huán)境(也就是DEBUG
為 False
的情況)中的錯誤報告中過濾的消息:sensitive_variables()
和sensitive_post_parameters()
。
sensitive_variables
(*variables)[source]
如果你的代碼中一個函數(shù)(視圖或者常規(guī)的回調(diào))使用可能含有敏感信息的局部變量,你可能需要使用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
變量的值會公開。
要想有順序地在錯誤報告中隱藏一個函數(shù)的所有局部變量,不要向sensitive_variables
裝飾器提供任何參數(shù):
@sensitive_variables()
def my_function():
...
使用多個裝飾器的時候
如果你想要隱藏的變量也是一個函數(shù)的參數(shù)(例如,下面例子中的user
),并且被裝飾的函數(shù)有多個裝飾器,你需要確保將@sensitive_variables
放在裝飾器鏈的頂端。這種方法也會隱藏函數(shù)參數(shù),盡管它通過其它裝飾器傳遞:
@sensitive_variables('user', 'pw', 'cc')
@some_decorator
@another_decorator
def process_info(user):
...
sensitive_post_parameters
(*parameters)[source]
如果你的代碼中一個視圖接收到了可能帶有敏感信息的,帶有POST 參數(shù)
的HttpRequest
對象,你可能需要使用sensitive_post_parameters
裝飾器,來阻止錯誤報告包含這些參數(shù)的值。
from 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參數(shù)的值會在錯誤報告中隱藏并且使用星號(**) 來代替,雖然name
變量的值會公開。
要想有順序地在錯誤報告中隱藏一個請求的所有POST 參數(shù),不要向sensitive_post_parameters
裝飾器提供任何參數(shù):
@sensitive_post_parameters()
def my_view(request):
...
所有POST參數(shù)按順序被過濾出特定django.contrib.auth.views
視圖的錯誤報告(login
, password_reset_confirm
, password_change
, add_view
和auth
中的user_change_password
),來防止像是用戶密碼這樣的敏感信息的泄露。
所有sensitive_variables()
和 sensitive_post_parameters()
分別用敏感變量的名字向被裝飾的函數(shù)添加注解,以及用POST敏感參數(shù)的名字向HttpRequest
對象添加注解,以便在錯誤產(chǎn)生時可以隨后過濾掉報告中的敏感信息。Django的默認錯誤包告過濾器django.views.debug.SafeExceptionReporterFilter
會完成實際的過濾操作。
產(chǎn)生錯誤報告的時候,這個過濾器使用裝飾器的注解來將相應(yīng)的值替換為星號 (**) 。如果你希望為你的整個站點覆寫或自定義這一默認的屬性,你需要定義你自己的過濾器類,并且通過DEFAULT_EXCEPTION_REPORTER_FILTER
設(shè)置來讓Django使用它。
DEFAULT_EXCEPTION_REPORTER_FILTER = 'path.to.your.CustomExceptionReporterFilter'
你也可能會以更精細的方式來控制在提供的視圖中使用哪種過濾器,通過設(shè)置 HttpRequest
的exception_reporter_filter
屬性。
def my_view(request):
if request.user.is_authenticated():
request.exception_reporter_filter = CustomExceptionReporterFilter()
...
你的自定義過濾器類需要繼承自 django.views.debug.SafeExceptionReporterFilter
,并且可能需要覆寫以下方法:
class SafeExceptionReporterFilter
[source]
SafeExceptionReporterFilter.``is_active
(request)[source]
如果其它方法中操作的過濾器已激活,返回True
。如果 DEBUG
為False
,通常過濾器是激活的。
SafeExceptionReporterFilter.``get_request_repr
(request)
Returns the representation string of the request object, that is, the value that would be returned by repr(request)
, except it uses the filtered dictionary of POST parameters as determined by SafeExceptionReporterFilter.get_post_parameters()
.
SafeExceptionReporterFilter.``get_post_parameters
(request)[source]
返回過濾后的POST參數(shù)字典。通常它會把敏感參數(shù)的值以星號 (**)替換。
SafeExceptionReporterFilter.``get_traceback_frame_variables
(request, _tbframe)[source]
返回過濾后的,所提供traceback幀的局部變量的字典。通常它會把敏感變量的值以星號 (**)替換。
另見
你也可以通過編寫自定義的exception middleware來建立自定義的錯誤報告。如果你編寫了自定義的錯誤處理器,模擬Django內(nèi)建的錯誤處理器,只在DEBUG
為 False
時報告或記錄錯誤是個好主意。
譯者:Django 文檔協(xié)作翻譯小組,原文:Tracking code errors by email。
本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請保留作者署名和文章出處。
Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。