django中間件及自定義中間件的實現(xiàn)方法
middleware
中間件就是在目標和結(jié)果之間進行的額外處理過程,在Django中就是request和response之間進行的處理,相對來說實現(xiàn)起來比較簡單,但是要注意它是對全局有效的,可以在全局范圍內(nèi)改變輸入和輸出結(jié)果,因此需要謹慎使用,否則不僅會造成難以定位的錯誤,而且可能會影響整體性能。
中間件有什么用
如果想要修改HttpRequest或者HttpResponse,就可以通過中間件來實現(xiàn)。
- 登陸認證:在中間件中加入登陸認證,所有請求就自動擁有登陸認證,如果需要放開部分路由,只需要特殊處理就可以了。
- 流量統(tǒng)計:可以針對一些渲染頁面統(tǒng)計訪問流量。
- 惡意請求攔截:統(tǒng)計IP請求次數(shù),可以進行頻次限制或者封禁IP。
本身django項目就帶有很多的中間件,在setting.py
里
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
之前我們通過post請求發(fā)起的時候,就需要先注釋掉csrf那一個中間件。
每個中間件的功能如下,
SecurityMiddleware
:為request/response提供了幾種安全改進;SessionMiddleware
:開啟session會話支持;CommonMiddleware
:基于APPEND_SLASH和PREPEND_WWW的設(shè)置來重寫URL,如果APPEND_SLASH設(shè)為True,并且初始URL 沒有以斜線結(jié)尾以及在URLconf 中沒找到對應(yīng)定義,這時形成一個斜線結(jié)尾的新URL;CsrfViewMiddleware
:添加跨站點請求偽造的保護,通過向POST表單添加一個隱藏的表單字段,并檢查請求中是否有正確的值;AuthenticationMiddleware
:在視圖函數(shù)執(zhí)行前向每個接收到的user對象添加HttpRequest屬性,表示當(dāng)前登錄的用戶,無它用不了request.user
。MessageMiddleware
:開啟基于Cookie和會話的消息支持XFrameOptionsMiddleware
:對點擊劫持的保護
除此以外, Django還提供了壓縮網(wǎng)站內(nèi)容的GZipMiddleware
,根據(jù)用戶請求語言返回不同內(nèi)容的LocaleMiddleware
和給GET請求附加條件的ConditionalGetMiddleware
。這些中間件都是可選的。
Django的中間件執(zhí)行順序
當(dāng)你在settings.py
注冊中間件時一定要要考慮中間件的執(zhí)行順序,中間件在request到達view之前是從上向下執(zhí)行的,在view執(zhí)行完后返回response過程中是從下向上執(zhí)行的,如下圖所示。舉個例子,如果你自定義的中間件有依賴于request.user
,那么你自定義的中間件一定要放在AuthenticationMiddleware
的后面
工作原理
HTTP Web服務(wù)器工作原理一般都是接收用戶發(fā)來的請求(request), 然后給出響應(yīng)(response)。Django也不例外,其一般工作方式是接收request對象和其它參數(shù),交由視圖(view)處理,然后給出它的響應(yīng)(respone)數(shù)據(jù): 渲染過的html文件或json格式的數(shù)據(jù)。然而在實際工作中Django并不是接收到request對象后,馬上交給視圖函數(shù)或類(view)處理,也不是在view執(zhí)行后立馬給用戶返回reponse。事實上Django最初接收的是HttpRequest對象,而不是request對象,正是中間件的作用把HttpRequest對象和user對象打包成了一個全局變量request對象,這樣你才可以View中使用request作為變量或者在模板中隨意調(diào)用request.user。
中間件(Middleware)在整個Django的request/response處理機制中的角色如下所示:
HttpRequest -> Middleware -> View -> Middleware -> HttpResponse
正是由于一個請求HttpRequest在傳遞給視圖View處理前要經(jīng)過中間件處理,經(jīng)過View處理后的響應(yīng)也要經(jīng)過中間件處理才能返回給用戶,我們可以編寫自己的中間件實現(xiàn)權(quán)限校驗,限制用戶請求、打印日志、改變輸出內(nèi)容等多種應(yīng)用場景,比如:
- 禁止特定IP地址的用戶或未登錄的用戶訪問我們的View視圖函數(shù)
- 對同一IP地址單位時間內(nèi)發(fā)送的請求數(shù)量做出限制
- 在View視圖函數(shù)執(zhí)行前記錄用戶的IP地址
- 在View視圖函數(shù)執(zhí)行前傳遞額外的變量或參數(shù)
- 在View視圖函數(shù)執(zhí)行前或執(zhí)行后把特定信息打印到log日志
- 在View視圖函數(shù)執(zhí)行后對reponse數(shù)據(jù)進行修改后返回給用戶
值得一提的是中間件對Django的輸入或輸出的改變是全局的,反之亦然。如果讓你希望對Django的輸入或輸出做出全局性的改變時,需要使用中間件。舉個例子,我們在裝飾器一文中介紹了如何使用@login_required裝飾器要求用戶必須先登錄才能訪問我們的視圖函數(shù)。試想我們有個網(wǎng)站絕大部分視圖函數(shù)都需要用戶登錄,每個視圖函數(shù)前面都需要加上@login_required裝飾器是比較傻的行為。借助于中間件,我們無需使用裝飾器即可全局實現(xiàn):只有登錄用戶才能訪問視圖函數(shù),匿名用戶跳轉(zhuǎn)到登錄頁面。實現(xiàn)原理也很簡單,在一個request到達視圖函數(shù)前,我們先對request.user是否驗證通過進行判斷,然后再進行跳轉(zhuǎn)。另外Django對POST表單中攜帶的CSRF token的全局校驗也是通過CsrfViewMiddleware這個中間件進行的,而不是通過單個裝飾器實現(xiàn)的。
自定義中間件
一般的中間件必須要有的兩個函數(shù)就是process_request
和process_response
如果自己定義中間件,首先在app里創(chuàng)建一個py文件,然后導(dǎo)入一些自帶的模塊
然后就是自定義類
class ReginaMiddleWare(MiddlewareMixin): def process_request(self,request): ''' :param request: 請求信息對象 :return: ''' print("reginaMiddleWare",request) def process_response(self,response,request): ''' :param response: 請求信息對象 :param request: 視圖函數(shù)返回的響應(yīng)體 :return: ''' print(response) return response
第三步就是把自己寫好的中間件按照目錄位置添加到settings文件當(dāng)中
MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'reginauser.reginaMiddleware.ReginaMiddleWare', 'reginauser.reginaMiddleware.IvanleeMiddleWare' ]
process_request功能
ip = request.META.get("REMOTE_ADDR") if ip in ['127.0.0.1','']: return HttpResponse("非法ip")
我們可以試一下本地地址,一旦process_request返回的不是默認的None,則表示攔截成功,那么也不會經(jīng)過IvanleeMiddleware,直接回到ReginaMiddleware的響應(yīng)處原路返回
process_response
def process_response(self,response,request): ''' :param response: 請求信息對象 :param request: 視圖函數(shù)返回的響應(yīng)體 :return: ''' print("ivanleeMiddleWare_response") response.content = response.content + b"<h1>I love Regina</h1>" //必須是用b去定義轉(zhuǎn)義類型 return response
那么在返回的時候,響應(yīng)內(nèi)容就是原有的helloworld和IloveRegina一起發(fā)送給請求者。
到此這篇關(guān)于django中間件及自定義中間件的實現(xiàn)方法的文章就介紹到這了,更多相關(guān)django自定義中間件 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解在OpenCV中實現(xiàn)的圖像標注技術(shù)
圖像標注在計算機視覺中很重要,計算機視覺是一種技術(shù),它允許計算機從數(shù)字圖像或視頻中獲得高水平的理解力,并以人類的方式觀察和解釋視覺信息,本文將重點討論在OpenCV的幫助下創(chuàng)建這些注釋,感興趣的朋友一起看看吧2022-06-06Python使用SQLAlchemy模塊實現(xiàn)操作數(shù)據(jù)庫
SQLAlchemy 是用Python編程語言開發(fā)的一個開源項目,它提供了SQL工具包和ORM對象關(guān)系映射工具,使用SQLAlchemy可以實現(xiàn)高效和高性能的數(shù)據(jù)庫訪問,下面我們就來學(xué)習(xí)一下SQLAlchemy模塊的具體應(yīng)用吧2023-11-11Django使用HTTP協(xié)議向服務(wù)器傳參方式小結(jié)
本文主要介紹了Django使用HTTP協(xié)議向服務(wù)器傳參方式小結(jié),用戶發(fā)送請求時攜帶的參數(shù)后端需要使用,而不同的發(fā)送參數(shù)的方式對應(yīng)了不同的提取參數(shù)的方式,本文就詳細的介紹一下2021-08-08python調(diào)用opencv實現(xiàn)貓臉檢測功能
這篇文章主要介紹了python調(diào)用opencv實現(xiàn)貓臉檢測功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-01-01Python爬取門戶論壇評論淺談Python未來發(fā)展方向
這篇文章主要介紹了如何實現(xiàn)Python爬取門戶論壇評論,附含圖片示例代碼,講解了詳細的操作過程,有需要的的朋友可以借鑒參考下,希望可以有所幫助2021-09-09Python簡單獲取網(wǎng)卡名稱及其IP地址的方法【基于psutil模塊】
這篇文章主要介紹了Python簡單獲取網(wǎng)卡名稱及其IP地址的方法,結(jié)合實例形式分析了Python基于psutil模塊針對本機網(wǎng)卡硬件信息的讀取操作簡單使用技巧,需要的朋友可以參考下2018-05-05python類的方法屬性與方法屬性的動態(tài)綁定代碼詳解
這篇文章主要介紹了python類的方法屬性與方法屬性的動態(tài)綁定代碼詳解,具有一定借鑒價值,需要的朋友可以參考下2017-12-12