Django中间件讲解

发布于:2025-06-19 ⋅ 阅读:(17) ⋅ 点赞:(0)

Django 中间件

一、Django 中间件基础

1.1 中间件工作原理

中间件是 Django 请求/响应处理的钩子框架。它是一个轻量级 的、底层的插件系统,用于全局修改 Django的输入或输出。每个中间件组件负责执行某些特定的功能。

1.2 中间件方法

class MiddlewareMixin:
    def __init__(self, get_response=None):
        self.get_response = get_response
        
    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        response = response or self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response

中间件类可以实现以下方法

  • process_request(request)
  • process_view(request, view_func, view_args, view_kwargs)
  • process_template_response(request, response)
  • process_exception(request, exception)
  • process_response(request, response)

二、自定义中间件示例

2.1 请求时间统计中间件

# middleware/timing.py
import time
from django.utils.deprecation import MiddlewareMixin
from django.core.cache import cache

class RequestTimingMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.start_time = time.time()
    
    def process_response(self, request, response):
        if hasattr(request, 'start_time'):
            total_time = time.time() - request.start_time
            response['X-Request-Time'] = f'{total_time:.2f}s'
            # 记录慢请求
            if total_time > 1.0:  # 超过1秒的请求
                cache.set(
                    f'slow_request_{request.path}_{time.time()}',
                    {
                        'path': request.path,
                        'method': request.method,
                        'time': total_time,
                        'user': str(request.user),
                    },
                    timeout=86400  # 24小时过期
                )
        return response

2.2 IP访问限制中间件

# middleware/ip_restriction.py
from django.core.exceptions import PermissionDenied
from django.core.cache import cache
from django.conf import settings

class IPRestrictionMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # 白名单IP列表
        self.allowed_ips = getattr(settings, 'ALLOWED_IPS', [])
        
    def __call__(self, request):
        ip = self.get_client_ip(request)
        
        # 检查IP访问频率
        if self.is_ip_banned(ip):
            raise PermissionDenied('访问频率过高,请稍后再试')
        # 记录IP访问次数
        self.record_ip_request(ip)
        response = self.get_response(request)
        return response
    
    def get_client_ip(self, request):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip
    
    def is_ip_banned(self, ip):
        if ip in self.allowed_ips:
            return False
            
        # 获取IP的访问次数
        key = f'ip_requests_{ip}'
        requests = cache.get(key, 0)
        # 如果1分钟内访问超过100次,则禁止访问
        return requests > 100
    
    def record_ip_request(self, ip):
        key = f'ip_requests_{ip}'
        timeout = 60  # 1分钟过期
        
        # 原子操作增加计数
        cache.add(key, 0, timeout)
        cache.incr(key)

2.3 用户行为日志中间件

# middleware/user_logging.py
import json
import logging
from django.utils.deprecation import MiddlewareMixin

logger = logging.getLogger('user_behavior')

class UserBehaviorMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.behavior_log = {
            'path': request.path,
            'method': request.method,
            'user_agent': request.META.get('HTTP_USER_AGENT', ''),
            'ip': self.get_client_ip(request),
            'user': str(request.user),
            'data': {}
        }
        
        # 记录请求数据
        if request.method in ['POST', 'PUT', 'PATCH']:
            try:
                request.behavior_log['data']['body'] = json.loads(request.body)
            except:
                request.behavior_log['data']['body'] = str(request.POST)
                
        if request.method == 'GET':
            request.behavior_log['data']['query'] = dict(request.GET)
    
    def process_response(self, request, response):
        if hasattr(request, 'behavior_log'):
            # 添加响应状态码
            request.behavior_log['status_code'] = response.status_code
            
            # 记录日志
            logger.info(
                'User Behavior',
                extra={'behavior': request.behavior_log}
            )
        return response
    
    def get_client_ip(self, request):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip

三、中间件配置与使用

# settings.py
MIDDLEWARE = [
  	 # 提供了一系列的安全功能,如通过设置 X-Content-Type-Options 和 X-XSS-Protection 等 HTTP 头来增强安全性。
    'django.middleware.security.SecurityMiddleware',
  	 # 用于管理会话(Sessions)。它负责在用户浏览网站时,在服务器和客户端之间保持状态。
    'django.contrib.sessions.middleware.SessionMiddleware',
     # 提供了一些常用功能,例如将请求对象中的 request.user 和 request.path 等属性设置为当前用户和请求的路径。
    'django.middleware.common.CommonMiddleware',
     # 用于防止跨站请求伪造(CSRF)。它检查 POST 请求中的 CSRF token,确保请求是由当前用户发出的。
    'django.middleware.csrf.CsrfViewMiddleware',
     # 用于处理用户认证。它检查每个请求,看是否有用户已通过认证,并将用户对象存储在请求对象中,以便于后续的视图函数使用。
    'django.contrib.auth.middleware.AuthenticationMiddleware',
     # 用于处理消息传递。它允许你在模板中显示消息(例如表单错误或成功消息)。
    'django.contrib.messages.middleware.MessageMiddleware',
     # 防止点击劫持攻击。它通过设置 HTTP 响应头 X-Frame-Options 来防止网页被嵌入到其他网站中。
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
     # 自定义中间件
    'middleware.timing.RequestTimingMiddleware',
    'middleware.ip_restriction.IPRestrictionMiddleware',
    'middleware.user_logging.UserBehaviorMiddleware',
]

请求进来时,中间件的执行顺序由上往下,响应返回时,由下往上


网站公告

今日签到

点亮在社区的每一天
去签到