Django - 中介軟體 (Middleware)
今天我們將學習 Django 中的重要組件——中介軟體(Middleware)。中介軟體是一種處理 HTTP 請求與回應的鉤子,能在請求到達視圖前、或回應送達瀏覽器前進行處理。通過中介軟體,我們可以實現請求攔截、回應修改、統計日誌等功能。
課程目標
- 瞭解中介軟體的基本概念與工作原理。
- 探索內建的中介軟體及其用途。
- 實現自訂中介軟體來滿足特定需求。
課程內容
1. 中介軟體的基本概念
1.1 中介軟體的作用
中介軟體是一種處理 HTTP 請求與回應的組件,負責:
- 攔截請求並執行操作,例如身份驗證、日誌記錄。
- 改變請求對象或添加額外的上下文數據。
- 改變回應內容或狀態碼。
1.2 中介軟體的處理流程
請求處理:
- 請求從瀏覽器發出後,依次通過所有已註冊的中介軟體。
- 每個中介軟體可對請求進行修改,或直接返回回應以中斷流程。
回應處理:
- 視圖返回回應後,該回應會再依次通過所有中介軟體。
- 每個中介軟體可以修改回應內容或狀態碼。
2. Django 的內建中介軟體
2.1 中介軟體列表
Django 預設的中介軟體可在 settings.py
中找到:
1
2
3
4
5
6
7
8
9
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',
]
2.2 常見內建中介軟體
SecurityMiddleware
:- 提供安全相關的功能,例如強制 HTTPS。
SessionMiddleware
:- 處理用戶會話數據。
CommonMiddleware
:- 處理常見的 HTTP 功能,如 URL 規範化。
CsrfViewMiddleware
:- 防止跨站請求偽造(CSRF)攻擊。
AuthenticationMiddleware
:- 將當前的用戶信息附加到請求對象中。
3. 自訂中介軟體
3.1 自訂中介軟體的結構
每個中介軟體類別都需要實現以下方法之一:
__init__()
:在啟動時初始化中介軟體。__call__()
:處理請求與回應。process_request()
:在視圖執行前處理請求。process_response()
:在回應返回前處理回應。
3.2 示例:請求日誌記錄
在 middleware.py
中新增一個自訂中介軟體:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import logging
logger = logging.getLogger(__name__)
class RequestLogMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 請求處理前的邏輯
logger.info(f"Request Path: {request.path}, Method: {request.method}")
response = self.get_response(request)
# 回應處理後的邏輯
return response
將其添加到 settings.py
的 MIDDLEWARE
中:
1
2
3
4
MIDDLEWARE = [
# 其他中介軟體...
'myapp.middleware.RequestLogMiddleware',
]
4. 高級中介軟體應用
4.1 防止惡意 IP 訪問
創建一個中介軟體來阻止特定 IP 的訪問:
1
2
3
4
5
6
7
8
9
10
11
class BlockIPMiddleware:
BLOCKED_IPS = ['192.168.1.100', '10.0.0.1']
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.META['REMOTE_ADDR'] in self.BLOCKED_IPS:
from django.http import HttpResponseForbidden
return HttpResponseForbidden("您的 IP 已被禁止訪問。")
return self.get_response(request)
4.2 在請求中添加額外數據
向每個請求對象中添加自訂屬性:
1
2
3
4
5
6
7
8
class AddCustomHeaderMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.custom_data = "這是額外的數據"
response = self.get_response(request)
return response
4.3 測試模式下模擬錯誤
模擬測試模式下的服務器錯誤:
1
2
3
4
5
6
7
8
class SimulateErrorMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.path == '/simulate-error/':
raise ValueError("模擬的服務器錯誤!")
return self.get_response(request)
5. 實踐:訪問計數器
目標
在所有請求中統計網站的總訪問次數。
實作
在 middleware.py
中新增:
1
2
3
4
5
6
7
8
9
10
11
12
from django.utils.deprecation import MiddlewareMixin
class VisitCountMiddleware(MiddlewareMixin):
visit_count = 0
def process_request(self, request):
VisitCountMiddleware.visit_count += 1
request.visit_count = VisitCountMiddleware.visit_count
def process_response(self, request, response):
response['X-Visit-Count'] = VisitCountMiddleware.visit_count
return response
在視圖中顯示訪問次數:
1
2
3
4
from django.http import JsonResponse
def visit_count_view(request):
return JsonResponse({'visit_count': request.visit_count})
6. 本日總結
- 瞭解了中介軟體的處理流程與作用。
- 使用內建中介軟體實現常見功能。
- 創建了多種自訂中介軟體應用,涵蓋日誌記錄、訪問限制、模擬錯誤等場景。
作業
- 建立一個中介軟體,記錄每個請求的處理時間。
- 創建一個中介軟體,攔截並重定向未登入用戶的所有請求到登入頁面。
- 在 Django 專案中實現一個「網站黑名單」功能,拒絕特定 IP 的請求。
本文章以 CC BY 4.0 授權