<!--
譯者:Github@wizardforcel
-->
# 中間件 #
這篇文檔介紹了Django自帶的所有中間件組件。 要查看關于如何使用它們以及如何編寫自己的中間件,請見中間件使用指導。
## 可用的中間件 ##
### 緩存中間件 ###
**class UpdateCacheMiddleware[source]**
**class FetchFromCacheMiddleware[source]**
開啟全站范圍的緩存。 如果開啟了這些緩存,任何一個由Django提供的頁面將會被緩存,緩存時長是由你在CACHE_MIDDLEWARE_SECONDS配置中定義的。詳見緩存文檔。
### "常用"的中間件 ###
**class CommonMiddleware[source]**
給完美主義者增加一些便利條件:
+ 禁止訪問DISALLOWED_USER_AGENTS中設置的用戶代理,這項配置應該是一個已編譯的正則表達式對象的列表。
+ 基于APPEND_SLASH和PREPEND_WWW的設置來重寫URL。
如果APPEND_SLASH設為True并且一開始的的URL沒有以斜線結尾,并且在URLconf中也沒找到對應定義,這時形成一個一個斜線結尾新的URL。如果這個新的URL存在于URLconf,這時Django會重定向請求到這個新URL上,否則,一開始的URL按正常情況處理。
比如,foo.com/bar將會被重定向到foo.com/bar/,如果你沒有為foo.com/bar定義有效的正則,但是為foo.com/bar/定義了有效的正則。
如果PREPEND_WWW設為True,前面缺少 "www."的url將會被重定向到相同但是以一個"www."開頭的url。
兩種選項都是為了規范化url。其中的哲學就是,任何一個url應該在一個地方僅存在一個。技術上來講,url foo.com/bar 區別于foo.com/bar/ -- 搜索引擎索引會把這里分開處理 -- 因此,最佳實踐就是規范化url。
+ 基于 USE_ETAGS 設置來處理ETag。如果設置USE_ETAGS為True,Django會通過MD5-hashing處理頁面的內容來為每一個頁面請求計算Etag,并且如果合適的話,它將會發送攜帶Not Modified的響應。
**CommonMiddleware.response_redirect_class**
```
Django 1.8中新增
```
默認為HttpResponsePermanentRedirect。它繼承了CommonMiddleware,并覆寫了屬性來自定義中間件發出的重定向。
**class BrokenLinkEmailsMiddleware[source]**
+ 向MANAGERS發送死鏈提醒郵件(詳見錯誤報告)。
### GZip中間件 ###
**class GZipMiddleware[source]**
> 警告
>
> 安全研究員最近發現,當壓縮技術(包括GZipMiddleware)用于一個網站的時候,網站會受到一些可能的攻擊。此外,這些方法可以用于破壞Django的CSRF保護。在你的站點使用GZipMiddleware之前,你應該先仔細考慮一下你的站點是否容易受到這些攻擊。 如果你不確定是否會受到這些影響,應該避免使用 GZipMiddleware。詳見the BREACH paper (PDF)和breachattack.com。
為支持GZip壓縮的瀏覽器(一些現代的瀏覽器)壓縮內容。
建議把這個中間件放到中間件配置列表的第一個,這樣壓縮響應內容的處理會到最后才 發生。
如果滿足下面條件的話,內容不會被壓縮:
+ 消息體的長度小于200個字節。
+ 響應已經設置了Content-Encoding協議頭。
+ 請求(瀏覽器)沒有發送包含gzip的Accept-Encoding協議頭。
你可以通過這個gzip_page()裝飾器使用獨立的GZip壓縮。
### 帶條件判斷的GET中間件 ###
**class ConditionalGetMiddleware[source]**
處理帶有條件判斷狀態GET操作。 如果一個請求包含 ETag 或者Last-Modified協議頭,并且請求包含If-None-Match或If-Modified-Since,這時響應會被 替換為HttpResponseNotModified。
另外,它會設置Date和Content-Length響應頭。
### 本地中間件 ###
**class LocaleMiddleware[source]**
基于請求中的數據開啟語言選擇。 它可以為每個用戶進行定制。 詳見國際化文檔。
**LocaleMiddleware.response_redirect_class**
默認為HttpResponseRedirect。繼承自LocaleMiddleware并覆寫了屬性來自定義中間件發出的重定向。
### 消息中間件 ###
**class MessageMiddleware[source]**
開啟基于cookie或會話的消息支持。詳見消息文檔。
### 安全中間件 ###
> 警告
>
> 如果你的部署環境允許的話,讓你的前端web服務器展示SecurityMiddleware提供的功能是個好主意。這樣一來,如果有任何請求沒有被Django處理(比如靜態媒體或用戶上傳的文件),他們會擁有和向Django應用的請求相同的保護。
**class SecurityMiddleware[source]**
```
Django 1.8中新增
```
django.middleware.security.SecurityMiddleware為請求/響應循環提供了幾種安全改進。每一種可以通過一個選項獨立開啟或關閉。
+ SECURE_BROWSER_XSS_FILTER
+ SECURE_CONTENT_TYPE_NOSNIFF
+ SECURE_HSTS_INCLUDE_SUBDOMAINS
+ SECURE_HSTS_SECONDS
+ SECURE_REDIRECT_EXEMPT
+ SECURE_SSL_HOST
+ SECURE_SSL_REDIRECT
### HTTP Strict Transport Security (HSTS) ###
對于那些應該只能通過HTTPS訪問的站點,你可以通過設置HSTS協議頭,通知現代的瀏覽器,拒絕用不安全的連接來連接你的域名。這會降低你受到SSL-stripping的中間人(MITM)攻擊的風險。
如果你將SECURE_HSTS_SECONDS設置為一個非零值,SecurityMiddleware會在所有的HTTPS響應中設置這個協議頭。
開啟HSTS的時候,首先使用一個小的值來測試它是個好主意,例如,讓SECURE_HSTS_SECONDS = 3600為一個小時。每當瀏覽器在你的站點看到HSTS協議頭,都會在提供的時間段內絕對使用不安全(HTTP)的方式連接到你的域名。一旦你確認你站點上的所有東西都以安全的方式提供(例如,HSTS并不會干擾任何事情),建議你增加這個值,這樣不常訪問你站點的游客也會被保護(比如,一般設置為31536000秒,一年)。
另外,如果你將 SECURE_HSTS_INCLUDE_SUBDOMAINS設置為True,,SecurityMiddleware會將includeSubDomains標簽添加到Strict-Transport-Security協議頭中。強烈推薦這樣做(假設所有子域完全使用HTTPS),否則你的站點仍舊有可能由于子域的不安全連接而受到攻擊。
> 警告
>
> HSTS策略在你的整個域中都被應用,不僅僅是你所設置協議頭的響應中的url。所以,如果你的整個域都設置為HTTPS only,你應該只使用HSTS策略。
>
> 適當遵循HSTS協議頭的瀏覽器,會通過顯示警告的方式,拒絕讓用戶連接到證書過期的、自行簽署的、或者其他SSL證書無效的站點。如果你使用了HSTS,確保你的證書處于一直有效的狀態!
> 注意
>
> 如果你的站點部署在負載均衡器或者反向代理之后,并且Strict-Transport-Security協議頭沒有添加到你的響應中,原因是Django有可能意識不到這是一個安全連接。你可能需要設置SECURE_PROXY_SSL_HEADER。
### X-Content-Type-Options: nosniff ###
一些瀏覽器會嘗試猜測他們所得內容的類型,而不是讀取Content-Type協議頭。雖然這樣有助于配置不當的服務器正常顯示內容,但也會導致安全問題。
如果你的站點允許用戶上傳文件,一些惡意的用戶可能會上傳一個精心構造的文件,當你覺得它無害的時候,文件會被瀏覽器解釋成HTML或者Javascript。
欲知更多有關這個協議頭和瀏覽器如何處理它的內容,你可以在IE安全博客中讀到它。
要防止瀏覽器猜測內容類型,并且強制它一直使用 Content-Type協議頭中提供的類型,你可以傳遞X-Content-Type-Options: nosniff協議頭。SecurityMiddleware將會對所有響應這樣做,如果SECURE_CONTENT_TYPE_NOSNIFF 設置為True。
注意在大多數Django不涉及處理上傳文件的部署環境中,這個設置不會有任何幫助。例如,如果你的MEDIA_URL被前端web服務器直接處理(例如nginx和Apache),你可能想要在那里設置這個協議頭。而在另一方面,如果你使用Django執行為了下載文件而請求授權之類的事情,并且你不能使用你的web服務器設置協議頭,這個設置會很有用。
### X-XSS-Protection: 1; mode=block ###
一些瀏覽器能夠屏蔽掉出現XSS攻擊的內容。通過尋找頁面中GET或者POST參數中的JavaScript內容來實現。如果JavaScript在服務器的響應中被重放,頁面就會停止渲染,并展示一個錯誤頁來取代。
X-XSS-Protection協議頭用來控制XSS過濾器的操作。
要在瀏覽器中啟用XSS過濾器,并且強制它一直屏蔽可疑的XSS攻擊,你可以在協議頭中傳遞X-XSS-Protection: 1; mode=block。 如果SECURE_BROWSER_XSS_FILTER設置為True,SecurityMiddleware會在所有響應中這樣做。
> 警告
>
> 瀏覽器的XSS過濾器是一個十分有效的手段,但是不要過度依賴它。它并不能檢測到所有的XSS攻擊,也不是所有瀏覽器都支持這一協議頭。確保你校驗和過濾了所有的輸入來防止XSS攻擊。
### SSL重定向 ###
如果你同時提供HTTP和HTTPS連接,大多數用戶會默認使用不安全的(HTTP)鏈接。為了更高的安全性,你應該講所有HTTP連接重定向到HTTP連接。
如果你將SECURE_SSL_REDIRECT設置為True,SecurityMiddleware會將HTTP鏈接永久地(HTTP 301,permanently)重定向到HTTPS連接。
> 注意
>
> 由于性能因素,最好在Django外面執行這些重定向,在nginx這種前端負載均衡器或者反向代理服務器中執行。SECURE_SSL_REDIRECT專門為這種部署情況而設計,當這不可選擇的時候。
如果SECURE_SSL_HOST設置有一個值,所有重定向都會發到值中的主機,而不是原始的請求主機。
如果你站點上的一些頁面應該以HTTP方式提供,并且不需要重定向到HTTPS,你可以SECURE_REDIRECT_EXEMPT設置中列出匹配那些url的正則表達式。
> 注意
>
> 如果你在負載均衡器或者反向代理服務器后面部署應用,而且Django不能辨別出什么時候一個請求是安全的,你可能需要設置SECURE_PROXY_SSL_HEADER。
### 會話中間件 ###
**class SessionMiddleware[source]**
開啟會話支持。詳見會話文檔。
### 站點中間件 ###
**class CurrentSiteMiddleware[source]**
```
Django 1.7中新增
```
向每個接收到的HttpRequest對象添加一個site屬性,表示當前的站點。詳見站點文檔。
### 認證中間件 ###
**class AuthenticationMiddleware[source]**
向每個接收到的HttpRequest對象添加user屬性,表示當前登錄的用戶。詳見web請求中的認證。
**class RemoteUserMiddleware[source]**
使用web服務器提供認證的中間件。詳見使用REMOTE_USER進行認證。
**class SessionAuthenticationMiddleware[source]**
```
Django 1.7中新增
```
當用戶修改密碼的時候使用戶的會話失效。詳見密碼更改時的會話失效。在MIDDLEWARE_CLASSES中,這個中間件必須出現在django.contrib.auth.middleware.AuthenticationMiddleware之后。
### CSRF保護中間件 ###
**class CsrfViewMiddleware[source]**
添加跨站點請求偽造的保護,通過向POST表單添加一個隱藏的表單字段,并檢查請求中是否有正確的值。詳見CSRF保護文檔。
### X-Frame-Options中間件 ###
**class XFrameOptionsMiddleware[source]**
通過X-Frame-Options協議頭進行簡單的點擊劫持保護。
## 中間件的排序 ##
下面是一些關于Django中間件排序的提示。
**UpdateCacheMiddleware**
放在修改大量協議頭的中間件(SessionMiddleware, GZipMiddleware, LocaleMiddleware)之前。
**GZipMiddleware**
放在任何可能修改或使用響應消息體的中間件之前。
放在UpdateCacheMiddleware之后:會修改大量的協議頭。
**ConditionalGetMiddleware**
放在CommonMiddleware之前:當USE_ETAGS = True時會使用它的Etag 協議頭。
**SessionMiddleware**
放在UpdateCacheMiddleware之后:會修改 大量協議頭。
**LocaleMiddleware**
放在SessionMiddleware(由于使用會話數據)和 CacheMiddleware(由于要修改大量協議頭)之后的最上面。
**CommonMiddleware**
放在任何可能修改相應的中間件之前(因為它會生成ETags)。
在GZipMiddleware之后,不會在壓縮后的內容上再去生成ETag。
盡可能放在靠上面的位置,因為APPEND_SLASH或者PREPEND_WWW設置為 True時會被重定向。
**CsrfViewMiddleware**
放在任何假設CSRF攻擊被處理的視圖中間件之前。
**AuthenticationMiddleware**
放在SessionMiddleware之后:因為它使用會話存儲。
**MessageMiddleware**
放在SessionMiddleware之后:會使用基于會話的存儲。
**FetchFromCacheMiddleware**
放在任何修改大量協議頭的中間件之后:協議頭被用來從緩存的哈希表中獲取值。
**FlatpageFallbackMiddleware**
應該放在最底下,因為他是中間件中的底牌。
**RedirectFallbackMiddleware**
應該放在最底下,因為他是中間件中的底牌。
- 新手入門
- 從零開始
- 概覽
- 安裝
- 教程
- 第1部分:模型
- 第2部分:管理站點
- 第3部分:視圖和模板
- 第4部分:表單和通用視圖
- 第5部分:測試
- 第6部分:靜態文件
- 高級教程
- 如何編寫可重用的應用
- 為Django編寫首個補丁
- 模型層
- 模型
- 模型語法
- 元選項
- 模型類
- 查詢集
- 執行查詢
- 查找表達式
- 模型的實例
- 實例方法
- 訪問關聯對象
- 遷移
- 模式編輯器
- 編寫遷移
- 高級
- 管理器
- 原始的SQL查詢
- 聚合
- 多數據庫
- 自定義查找
- 條件表達式
- 數據庫函數
- 其它
- 遺留的數據庫
- 提供初始數據
- 優化數據庫訪問
- 視圖層
- 基礎
- URL配置
- 視圖函數
- 快捷函數
- 裝飾器
- 參考
- 內建的視圖
- TemplateResponse 對象
- 文件上傳
- 概覽
- File 對象
- 儲存API
- 管理文件
- 自定義存儲
- 基于類的視圖
- 概覽
- 內建顯示視圖
- 內建編輯視圖
- API參考
- 分類索引
- 高級
- 生成 CSV
- 生成 PDF
- 中間件
- 概覽
- 內建的中間件類
- 模板層
- 基礎
- 面向設計師
- 語言概覽
- 人性化
- 面向程序員
- 表單
- 基礎
- 概覽
- 表單API
- 內建的Widget
- 高級
- 整合媒體
- 開發過程
- 設置
- 概覽
- 應用程序
- 異常
- 概覽
- django-admin 和 manage.py
- 添加自定義的命令
- 測試
- 介紹
- 部署
- 概述
- WSGI服務器
- 部署靜態文件
- 通過email追蹤代碼錯誤
- Admin
- 管理操作
- 管理文檔生成器
- 安全
- 安全概述
- 說明Django中的安全問題
- 點擊劫持保護
- 加密簽名
- 國際化和本地化
- 概述
- 本地化WEB UI格式化輸入
- “本地特色”
- 常見的網站應用工具
- 認證
- 概覽
- 使用認證系統
- 密碼管理
- 日志
- 分頁
- 會話
- 數據驗證
- 其它核心功能
- 按需內容處理
- 重定向
- 信號
- 系統檢查框架