django中間件以及自定義中間件

来源:https://www.cnblogs.com/ivanlee717/archive/2022/11/03/16853099.html
-Advertisement-
Play Games

middleware 中間件就是在目標和結果之間進行的額外處理過程,在Django中就是request和response之間進行的處理,相對來說實現起來比較簡單,但是要註意它是對全局有效的,可以在全局範圍內改變輸入和輸出結果,因此需要謹慎使用,否則不僅會造成難以定位的錯誤,而且可能會影響整體性能。 ...


middleware

中間件就是在目標結果之間進行的額外處理過程,在Django中就是request和response之間進行的處理,相對來說實現起來比較簡單,但是要註意它是對全局有效的,可以在全局範圍內改變輸入和輸出結果,因此需要謹慎使用,否則不僅會造成難以定位的錯誤,而且可能會影響整體性能。

中間件有什麼用

如果想要修改HttpRequest或者HttpResponse,就可以通過中間件來實現。

  • 登陸認證:在中間件中加入登陸認證,所有請求就自動擁有登陸認證,如果需要放開部分路由,只需要特殊處理就可以了。
  • 流量統計:可以針對一些渲染頁面統計訪問流量。
  • 惡意請求攔截:統計IP請求次數,可以進行頻次限制或者封禁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請求發起的時候,就需要先註釋掉csrf那一個中間件。

每個中間件的功能如下,

  • SecurityMiddleware:為request/response提供了幾種安全改進;
  • SessionMiddleware:開啟session會話支持;
  • CommonMiddleware:基於APPEND_SLASH和PREPEND_WWW的設置來重寫URL,如果APPEND_SLASH設為True,並且初始URL 沒有以斜線結尾以及在URLconf 中沒找到對應定義,這時形成一個斜線結尾的新URL;
  • CsrfViewMiddleware:添加跨站點請求偽造的保護,通過向POST表單添加一個隱藏的表單欄位,並檢查請求中是否有正確的值;
  • AuthenticationMiddleware:在視圖函數執行前向每個接收到的user對象添加HttpRequest屬性,表示當前登錄的用戶,無它用不了request.user
  • MessageMiddleware:開啟基於Cookie和會話的消息支持
  • XFrameOptionsMiddleware:對點擊劫持的保護

除此以外, Django還提供了壓縮網站內容的GZipMiddleware,根據用戶請求語言返回不同內容的LocaleMiddleware和給GET請求附加條件的ConditionalGetMiddleware。這些中間件都是可選的。

Django的中間件執行順序

當你在settings.py註冊中間件時一定要要考慮中間件的執行順序,中間件在request到達view之前是從上向下執行的,在view執行完後返回response過程中是從下向上執行的,如下圖所示。舉個例子,如果你自定義的中間件有依賴於request.user,那麼你自定義的中間件一定要放在AuthenticationMiddleware的後面

image-20221102232915281

工作原理

HTTP Web伺服器工作原理一般都是接收用戶發來的請求(request), 然後給出響應(response)。Django也不例外,其一般工作方式是接收request對象和其它參數,交由視圖(view)處理,然後給出它的響應(respone)數據: 渲染過的html文件或json格式的數據。然而在實際工作中Django並不是接收到request對象後,馬上交給視圖函數或類(view)處理,也不是在view執行後立馬給用戶返回reponse。事實上Django最初接收的是HttpRequest對象,而不是request對象,正是中間件的作用把HttpRequest對象和user對象打包成了一個全局變數request對象,這樣你才可以View中使用request作為變數或者在模板中隨意調用request.user。

image-20221102233759566

中間件(Middleware)在整個Django的request/response處理機制中的角色如下所示:

HttpRequest -> Middleware -> View -> Middleware -> HttpResponse

正是由於一個請求HttpRequest在傳遞給視圖View處理前要經過中間件處理,經過View處理後的響應也要經過中間件處理才能返回給用戶,我們可以編寫自己的中間件實現許可權校驗,限制用戶請求、列印日誌、改變輸出內容等多種應用場景,比如:

  • 禁止特定IP地址的用戶或未登錄的用戶訪問我們的View視圖函數
  • 對同一IP地址單位時間內發送的請求數量做出限制
  • 在View視圖函數執行前記錄用戶的IP地址
  • 在View視圖函數執行前傳遞額外的變數或參數
  • 在View視圖函數執行前或執行後把特定信息列印到log日誌
  • 在View視圖函數執行後對reponse數據進行修改後返回給用戶

值得一提的是中間件對Django的輸入或輸出的改變是全局的,反之亦然。如果讓你希望對Django的輸入或輸出做出全局性的改變時,需要使用中間件。舉個例子,我們在裝飾器一文中介紹瞭如何使用@login_required裝飾器要求用戶必須先登錄才能訪問我們的視圖函數。試想我們有個網站絕大部分視圖函數都需要用戶登錄,每個視圖函數前面都需要加上@login_required裝飾器是比較傻的行為。藉助於中間件,我們無需使用裝飾器即可全局實現:只有登錄用戶才能訪問視圖函數,匿名用戶跳轉到登錄頁面。實現原理也很簡單,在一個request到達視圖函數前,我們先對request.user是否驗證通過進行判斷,然後再進行跳轉。另外Django對POST表單中攜帶的CSRF token的全局校驗也是通過CsrfViewMiddleware這個中間件進行的,而不是通過單個裝飾器實現的。

自定義中間件

image-20221102234020308

一般的中間件必須要有的兩個函數就是process_requestprocess_response

如果自己定義中間件,首先在app里創建一個py文件,然後導入一些自帶的模塊

from django.utils.deprecation import MiddlewareMixin

然後就是自定義類

class ReginaMiddleWare(MiddlewareMixin):
    def process_request(self,request):
        '''

        :param request: 請求信息對象
        :return:
        '''
        print("reginaMiddleWare",request)
    def process_response(self,response,request):
        '''

        :param response: 請求信息對象
        :param request: 視圖函數返回的響應體
        :return:
        '''
        print(response)
        return response

第三步就是把自己寫好的中間件按照目錄位置添加到settings文件當中

MIDDLEWARE = [
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'reginauser.reginaMiddleware.ReginaMiddleWare',
    'reginauser.reginaMiddleware.IvanleeMiddleWare'
]
reginaMiddleWare <WSGIRequest: GET '/md/'>
ivanleeMiddleWare <WSGIRequest: GET '/md/'>
<WSGIRequest: GET '/md/'>
ivanleemiddleware <WSGIRequest: GET '/md/'>
reginamiddleware <WSGIRequest: GET '/md/'>

process_request功能

image-20221103002922820

ip = request.META.get("REMOTE_ADDR")
if ip in ['127.0.0.1','']:
  return HttpResponse("非法ip")

我們可以試一下本地地址,一旦process_request返回的不是預設的None,則表示攔截成功,那麼也不會經過IvanleeMiddleware,直接回到ReginaMiddleware的響應處原路返回

process_response

    def process_response(self,response,request):
        '''

        :param response: 請求信息對象
        :param request: 視圖函數返回的響應體
        :return:
        '''
        print("ivanleeMiddleWare_response")
        respnse = response.content + "<h1>I love Regina</h1>"
        return respnse

那麼在返回的時候,響應內容就是原有的helloworld和IloveRegina一起發送給請求者。

本文來自博客園,作者:ivanlee717,轉載請註明原文鏈接:https://www.cnblogs.com/ivanlee717/p/16853099.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 第四期 · 將部分數據存儲至Mysql,使用axios通過golang搭建的http伺服器獲取數據。 新建資料庫 DROP DATABASE VUE; create database if not exists vue; use vue; JSON TO MYSQL JSON to MySQL (t ...
  • 1、媒體元素 音頻和視頻 <!-- 音頻和視頻 src:資源路徑 controls:控制條 autoplay:自動播放--> <video src="" controls outoplay></video><audio src="" controls outoplay></autio> 2、頁面結構 ...
  • 好家伙,本篇介紹如何實現"刪"功能 來看效果, 資料庫 (自然是沒什麼毛病) "增"搞定了,其實"刪"非常簡單 (我不會告訴你我是為了水一篇博客才把他們兩個分開寫,嘿嘿) 邏輯簡潔明瞭: 首先,看見你要刪除的數據,點"刪除", 隨後,①拿到當前這條數據的Id,向後臺發請求網路, 然後,②後端刪除該字 ...
  • 怎麼樣子盒子能撐起父盒子? 從行內元素跟塊元素來看: 一般情況下,行內元素只能包含數據和其他行內元素。 而塊級元素可以包含行內元素和其他塊級元素. 塊級元素內部可以嵌套塊級元素或行內元素。 建議行內元素裡面只嵌套行內元素。 行內元素只能包含內容或者其它行內元素,寬度和長度依據內容而定,不可以設置,可 ...
  • ####事件組成,事件三要素 1.事件源:事件觸發的按鈕,比如滑鼠點擊某個圖標跳轉頁面,那個圖標就稱為事件源。 比如, <button>我是一個按鈕,也是事件源</button> 2.事件類型:事件觸發的方式,怎麼觸發一個事件,比如滑鼠點擊(oncilck),滑鼠經過,還是按下鬆開觸發。 3.事件處 ...
  • ES標準下中的let,var和const let會報重覆聲明,var則比較隨意,重不重覆無所謂 // 使用 var 的時候重覆聲明變數是沒問題的,只不過就是後面會把前面覆蓋掉 var num = 100 var num = 200 // 使用 let 重覆聲明變數的時候就會報錯了 let num = ...
  • There are a thousand Hamlets in a thousand people's eyes. 威廉·莎士比亞 免責聲明:以下充滿個人觀點,辯證學習 React 目前開發以函數組件為主,輔以 hooks 實現大部分的頁面邏輯。目前數棧的 react 版本是 16.13.1,該版本 ...
  • 為了提升應用穩定性,我們對前端項目開展了腳本異常治理的工作,對生產上報的js error進行了整體排查,試圖通過降低腳本異常的發生頻次來提升相關告警的準確率,結合最近在這方面閱讀的相關資料,嘗試階段性的做個總結,下麵我們來介紹下js異常處理的一些經驗。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...