這篇文檔介紹了Django自帶的所有中間件組件。 要查看關(guān)于如何使用它們以及如何編寫自己的中間件,請(qǐng)見(jiàn)中間件使用指導(dǎo)。
class UpdateCacheMiddleware[source]
class FetchFromCacheMiddleware[source]
開(kāi)啟全站范圍的緩存。 如果開(kāi)啟了這些緩存,任何一個(gè)由Django提供的頁(yè)面將會(huì)被緩存,緩存時(shí)長(zhǎng)是由你在CACHE_MIDDLEWARE_SECONDS配置中定義的。詳見(jiàn)緩存文檔。
class CommonMiddleware[source]
給完美主義者增加一些便利條件:
如果APPEND_SLASH設(shè)為True并且一開(kāi)始的的URL沒(méi)有以斜線結(jié)尾,并且在URLconf中也沒(méi)找到對(duì)應(yīng)定義,這時(shí)形成一個(gè)一個(gè)斜線結(jié)尾新的URL。如果這個(gè)新的URL存在于URLconf,這時(shí)Django會(huì)重定向請(qǐng)求到這個(gè)新URL上,否則,一開(kāi)始的URL按正常情況處理。
比如,foo.com/bar將會(huì)被重定向到foo.com/bar/,如果你沒(méi)有為foo.com/bar定義有效的正則,但是為foo.com/bar/定義了有效的正則。
如果PREPEND_WWW設(shè)為True,前面缺少 "www."的url將會(huì)被重定向到相同但是以一個(gè)"www."開(kāi)頭的url。
兩種選項(xiàng)都是為了規(guī)范化url。其中的哲學(xué)就是,任何一個(gè)url應(yīng)該在一個(gè)地方僅存在一個(gè)。技術(shù)上來(lái)講,url foo.com/bar 區(qū)別于foo.com/bar/ -- 搜索引擎索引會(huì)把這里分開(kāi)處理 -- 因此,最佳實(shí)踐就是規(guī)范化url。
CommonMiddleware.response_redirect_class
Django 1.8中新增
默認(rèn)為HttpResponsePermanentRedirect。它繼承了CommonMiddleware,并覆寫了屬性來(lái)自定義中間件發(fā)出的重定向。
class BrokenLinkEmailsMiddleware[source]
class GZipMiddleware[source]
警告
安全研究員最近發(fā)現(xiàn),當(dāng)壓縮技術(shù)(包括GZipMiddleware)用于一個(gè)網(wǎng)站的時(shí)候,網(wǎng)站會(huì)受到一些可能的攻擊。此外,這些方法可以用于破壞Django的CSRF保護(hù)。在你的站點(diǎn)使用GZipMiddleware之前,你應(yīng)該先仔細(xì)考慮一下你的站點(diǎn)是否容易受到這些攻擊。 如果你不確定是否會(huì)受到這些影響,應(yīng)該避免使用 GZipMiddleware。詳見(jiàn)the BREACH paper (PDF)和breachattack.com。
為支持GZip壓縮的瀏覽器(一些現(xiàn)代的瀏覽器)壓縮內(nèi)容。
建議把這個(gè)中間件放到中間件配置列表的第一個(gè),這樣壓縮響應(yīng)內(nèi)容的處理會(huì)到最后才 發(fā)生。
如果滿足下面條件的話,內(nèi)容不會(huì)被壓縮:
你可以通過(guò)這個(gè)gzip_page()裝飾器使用獨(dú)立的GZip壓縮。
class ConditionalGetMiddleware[source]
處理帶有條件判斷狀態(tài)GET操作。 如果一個(gè)請(qǐng)求包含 ETag 或者Last-Modified協(xié)議頭,并且請(qǐng)求包含If-None-Match或If-Modified-Since,這時(shí)響應(yīng)會(huì)被 替換為HttpResponseNotModified。
另外,它會(huì)設(shè)置Date和Content-Length響應(yīng)頭。
class LocaleMiddleware[source]
基于請(qǐng)求中的數(shù)據(jù)開(kāi)啟語(yǔ)言選擇。 它可以為每個(gè)用戶進(jìn)行定制。 詳見(jiàn)國(guó)際化文檔。
LocaleMiddleware.response_redirect_class
默認(rèn)為HttpResponseRedirect。繼承自LocaleMiddleware并覆寫了屬性來(lái)自定義中間件發(fā)出的重定向。
class MessageMiddleware[source]
開(kāi)啟基于cookie或會(huì)話的消息支持。詳見(jiàn)消息文檔。
警告
如果你的部署環(huán)境允許的話,讓你的前端web服務(wù)器展示SecurityMiddleware提供的功能是個(gè)好主意。這樣一來(lái),如果有任何請(qǐng)求沒(méi)有被Django處理(比如靜態(tài)媒體或用戶上傳的文件),他們會(huì)擁有和向Django應(yīng)用的請(qǐng)求相同的保護(hù)。
class SecurityMiddleware[source]
Django 1.8中新增
django.middleware.security.SecurityMiddleware為請(qǐng)求/響應(yīng)循環(huán)提供了幾種安全改進(jìn)。每一種可以通過(guò)一個(gè)選項(xiàng)獨(dú)立開(kāi)啟或關(guān)閉。
對(duì)于那些應(yīng)該只能通過(guò)HTTPS訪問(wèn)的站點(diǎn),你可以通過(guò)設(shè)置HSTS協(xié)議頭,通知現(xiàn)代的瀏覽器,拒絕用不安全的連接來(lái)連接你的域名。這會(huì)降低你受到SSL-stripping的中間人(MITM)攻擊的風(fēng)險(xiǎn)。
如果你將SECURE_HSTS_SECONDS設(shè)置為一個(gè)非零值,SecurityMiddleware會(huì)在所有的HTTPS響應(yīng)中設(shè)置這個(gè)協(xié)議頭。
開(kāi)啟HSTS的時(shí)候,首先使用一個(gè)小的值來(lái)測(cè)試它是個(gè)好主意,例如,讓SECURE_HSTS_SECONDS = 3600為一個(gè)小時(shí)。每當(dāng)瀏覽器在你的站點(diǎn)看到HSTS協(xié)議頭,都會(huì)在提供的時(shí)間段內(nèi)絕對(duì)使用不安全(HTTP)的方式連接到你的域名。一旦你確認(rèn)你站點(diǎn)上的所有東西都以安全的方式提供(例如,HSTS并不會(huì)干擾任何事情),建議你增加這個(gè)值,這樣不常訪問(wèn)你站點(diǎn)的游客也會(huì)被保護(hù)(比如,一般設(shè)置為31536000秒,一年)。
另外,如果你將 SECURE_HSTS_INCLUDE_SUBDOMAINS設(shè)置為True,,SecurityMiddleware會(huì)將includeSubDomains標(biāo)簽添加到Strict-Transport-Security協(xié)議頭中。強(qiáng)烈推薦這樣做(假設(shè)所有子域完全使用HTTPS),否則你的站點(diǎn)仍舊有可能由于子域的不安全連接而受到攻擊。
警告
HSTS策略在你的整個(gè)域中都被應(yīng)用,不僅僅是你所設(shè)置協(xié)議頭的響應(yīng)中的url。所以,如果你的整個(gè)域都設(shè)置為HTTPS only,你應(yīng)該只使用HSTS策略。
適當(dāng)遵循HSTS協(xié)議頭的瀏覽器,會(huì)通過(guò)顯示警告的方式,拒絕讓用戶連接到證書過(guò)期的、自行簽署的、或者其他SSL證書無(wú)效的站點(diǎn)。如果你使用了HSTS,確保你的證書處于一直有效的狀態(tài)!
注意
如果你的站點(diǎn)部署在負(fù)載均衡器或者反向代理之后,并且Strict-Transport-Security協(xié)議頭沒(méi)有添加到你的響應(yīng)中,原因是Django有可能意識(shí)不到這是一個(gè)安全連接。你可能需要設(shè)置SECURE_PROXY_SSL_HEADER。
一些瀏覽器會(huì)嘗試猜測(cè)他們所得內(nèi)容的類型,而不是讀取Content-Type協(xié)議頭。雖然這樣有助于配置不當(dāng)?shù)姆?wù)器正常顯示內(nèi)容,但也會(huì)導(dǎo)致安全問(wèn)題。
如果你的站點(diǎn)允許用戶上傳文件,一些惡意的用戶可能會(huì)上傳一個(gè)精心構(gòu)造的文件,當(dāng)你覺(jué)得它無(wú)害的時(shí)候,文件會(huì)被瀏覽器解釋成HTML或者Javascript。
欲知更多有關(guān)這個(gè)協(xié)議頭和瀏覽器如何處理它的內(nèi)容,你可以在IE安全博客中讀到它。
要防止瀏覽器猜測(cè)內(nèi)容類型,并且強(qiáng)制它一直使用 Content-Type協(xié)議頭中提供的類型,你可以傳遞X-Content-Type-Options: nosniff協(xié)議頭。SecurityMiddleware將會(huì)對(duì)所有響應(yīng)這樣做,如果SECURE_CONTENT_TYPE_NOSNIFF 設(shè)置為True。
注意在大多數(shù)Django不涉及處理上傳文件的部署環(huán)境中,這個(gè)設(shè)置不會(huì)有任何幫助。例如,如果你的MEDIA_URL被前端web服務(wù)器直接處理(例如nginx和Apache),你可能想要在那里設(shè)置這個(gè)協(xié)議頭。而在另一方面,如果你使用Django執(zhí)行為了下載文件而請(qǐng)求授權(quán)之類的事情,并且你不能使用你的web服務(wù)器設(shè)置協(xié)議頭,這個(gè)設(shè)置會(huì)很有用。
一些瀏覽器能夠屏蔽掉出現(xiàn)XSS攻擊的內(nèi)容。通過(guò)尋找頁(yè)面中GET或者POST參數(shù)中的JavaScript內(nèi)容來(lái)實(shí)現(xiàn)。如果JavaScript在服務(wù)器的響應(yīng)中被重放,頁(yè)面就會(huì)停止渲染,并展示一個(gè)錯(cuò)誤頁(yè)來(lái)取代。
X-XSS-Protection協(xié)議頭用來(lái)控制XSS過(guò)濾器的操作。
要在瀏覽器中啟用XSS過(guò)濾器,并且強(qiáng)制它一直屏蔽可疑的XSS攻擊,你可以在協(xié)議頭中傳遞X-XSS-Protection: 1; mode=block。 如果SECURE_BROWSER_XSS_FILTER設(shè)置為True,SecurityMiddleware會(huì)在所有響應(yīng)中這樣做。
警告
瀏覽器的XSS過(guò)濾器是一個(gè)十分有效的手段,但是不要過(guò)度依賴它。它并不能檢測(cè)到所有的XSS攻擊,也不是所有瀏覽器都支持這一協(xié)議頭。確保你校驗(yàn)和過(guò)濾了所有的輸入來(lái)防止XSS攻擊。
如果你同時(shí)提供HTTP和HTTPS連接,大多數(shù)用戶會(huì)默認(rèn)使用不安全的(HTTP)鏈接。為了更高的安全性,你應(yīng)該講所有HTTP連接重定向到HTTP連接。
如果你將SECURE_SSL_REDIRECT設(shè)置為True,SecurityMiddleware會(huì)將HTTP鏈接永久地(HTTP 301,permanently)重定向到HTTPS連接。
注意
由于性能因素,最好在Django外面執(zhí)行這些重定向,在nginx這種前端負(fù)載均衡器或者反向代理服務(wù)器中執(zhí)行。SECURE_SSL_REDIRECT專門為這種部署情況而設(shè)計(jì),當(dāng)這不可選擇的時(shí)候。
如果SECURE_SSL_HOST設(shè)置有一個(gè)值,所有重定向都會(huì)發(fā)到值中的主機(jī),而不是原始的請(qǐng)求主機(jī)。
如果你站點(diǎn)上的一些頁(yè)面應(yīng)該以HTTP方式提供,并且不需要重定向到HTTPS,你可以SECURE_REDIRECT_EXEMPT設(shè)置中列出匹配那些url的正則表達(dá)式。
注意
如果你在負(fù)載均衡器或者反向代理服務(wù)器后面部署應(yīng)用,而且Django不能辨別出什么時(shí)候一個(gè)請(qǐng)求是安全的,你可能需要設(shè)置SECURE_PROXY_SSL_HEADER。
class SessionMiddleware[source]
開(kāi)啟會(huì)話支持。詳見(jiàn)會(huì)話文檔。
class CurrentSiteMiddleware[source]
Django 1.7中新增
向每個(gè)接收到的HttpRequest對(duì)象添加一個(gè)site屬性,表示當(dāng)前的站點(diǎn)。詳見(jiàn)站點(diǎn)文檔。
class AuthenticationMiddleware[source]
向每個(gè)接收到的HttpRequest對(duì)象添加user屬性,表示當(dāng)前登錄的用戶。詳見(jiàn)web請(qǐng)求中的認(rèn)證。
class RemoteUserMiddleware[source]
使用web服務(wù)器提供認(rèn)證的中間件。詳見(jiàn)使用REMOTE_USER進(jìn)行認(rèn)證。
class SessionAuthenticationMiddleware[source]
Django 1.7中新增
當(dāng)用戶修改密碼的時(shí)候使用戶的會(huì)話失效。詳見(jiàn)密碼更改時(shí)的會(huì)話失效。在MIDDLEWARE_CLASSES中,這個(gè)中間件必須出現(xiàn)在django.contrib.auth.middleware.AuthenticationMiddleware之后。
class CsrfViewMiddleware[source]
添加跨站點(diǎn)請(qǐng)求偽造的保護(hù),通過(guò)向POST表單添加一個(gè)隱藏的表單字段,并檢查請(qǐng)求中是否有正確的值。詳見(jiàn)CSRF保護(hù)文檔。
class XFrameOptionsMiddleware[source]
通過(guò)X-Frame-Options協(xié)議頭進(jìn)行簡(jiǎn)單的點(diǎn)擊劫持保護(hù)。
下面是一些關(guān)于Django中間件排序的提示。
UpdateCacheMiddleware
放在修改大量協(xié)議頭的中間件(SessionMiddleware, GZipMiddleware, LocaleMiddleware)之前。
GZipMiddleware
放在任何可能修改或使用響應(yīng)消息體的中間件之前。
放在UpdateCacheMiddleware之后:會(huì)修改大量的協(xié)議頭。
ConditionalGetMiddleware
放在CommonMiddleware之前:當(dāng)USE_ETAGS = True時(shí)會(huì)使用它的Etag 協(xié)議頭。
SessionMiddleware
放在UpdateCacheMiddleware之后:會(huì)修改 大量協(xié)議頭。
LocaleMiddleware
放在SessionMiddleware(由于使用會(huì)話數(shù)據(jù))和 CacheMiddleware(由于要修改大量協(xié)議頭)之后的最上面。
CommonMiddleware
放在任何可能修改相應(yīng)的中間件之前(因?yàn)樗鼤?huì)生成ETags)。
在GZipMiddleware之后,不會(huì)在壓縮后的內(nèi)容上再去生成ETag。
盡可能放在靠上面的位置,因?yàn)锳PPEND_SLASH或者PREPEND_WWW設(shè)置為 True時(shí)會(huì)被重定向。
CsrfViewMiddleware
放在任何假設(shè)CSRF攻擊被處理的視圖中間件之前。
AuthenticationMiddleware
放在SessionMiddleware之后:因?yàn)樗褂脮?huì)話存儲(chǔ)。
MessageMiddleware
放在SessionMiddleware之后:會(huì)使用基于會(huì)話的存儲(chǔ)。
FetchFromCacheMiddleware
放在任何修改大量協(xié)議頭的中間件之后:協(xié)議頭被用來(lái)從緩存的哈希表中獲取值。
FlatpageFallbackMiddleware
應(yīng)該放在最底下,因?yàn)樗侵虚g件中的底牌。
RedirectFallbackMiddleware
應(yīng)該放在最底下,因?yàn)樗侵虚g件中的底牌。