关键词

深入理解Django的中间件middleware

深入理解 Django 的中间件 Middleware

Django 的中间件是一种可插拔的方式,可以处理用户请求和响应的过程,常用于处理日志、安全、缓存、权限等。本文介绍如何使用 Django 的中间件,并提供两个示例说明。

1. 中间件的基本结构

Django 中间件的基本结构包括了三个方法:

  • __init__(self, get_response):在中间件被初始化时执行,可用于对中间件进行设定。
  • __call__(self, request):每次接受请求时都会执行,可用于处理请求前的逻辑。
  • process_response(self, request, response):在视图响应后执行,可用于处理响应后的逻辑。

这三个方法中,只有 __call__ 是必须实现的方法,其他两个方法是可选的。

下面看一个简单的中间件示例。

class SwapMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        request.url, request.path = request.path, request.url
        response = self.get_response(request)
        return response

上面代码中,定义了一个简单的中间件类 SwapMiddleware。该中间件只有 __init____call__ 两个方法。在 __init__ 方法中,我们通过接收 get_response 参数来保存访问视图函数时的回调函数。而在 __call__ 方法中,我们将 request 的 url 和 path 交换位置,并调用回调函数 self.get_response(request) 拿到响应。(该例子是将 request 中的 url 和 path 交换位置,纯属娱乐,开发中并不会使用)

2. 中间件的配置

Django 的中间件需要在 django.settings.py 文件中进行配置。中间件按照顺序依次执行,如果前面的中间件处理了请求,那么后面的中间件将不再执行处理逻辑。这点需结合中间件的定义来理解。一般而言,中间件配置有两个关键字:

  • MIDDLEWARE:是一个中间件列表,最好指定顺序。
  • MIDDLEWARE_CLASSES:是一个中间件类路径列表,大多数 legacy 代码使用这个指令。

下面是一个完整的配置示例:

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',
]

上面代码中,定义了 Django 官方推荐的中间件顺序。

3. 示例一:处理请求头

假设我们的网站需要验证每个请求中是否有指定的请求头 Authorization,并获取请求头的值作为当前用户的 token,那么我们可以编写一个自定义中间件来完成该功能。代码如下:

class TokenMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        authorization = request.META.get('HTTP_AUTHORIZATION')
        request.token = authorization.split()[1] if authorization else None
        response = self.get_response(request)
        return response

上面这个自定义中间件的作用是通过 request.META 获取请求头 Authorization,并从中获取值作为 token 存储在 request 对象中,便于后续的视图函数使用。

4. 示例二:限制访问频率

假设我们的网站需要限制用户访问频率,每秒钟只允许访问一次。那么我们可以编写一个自定义中间件来处理该功能。代码如下:

import time

class RateLimitMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.limits = {}  # 记录各 IP 的上次访问时间

    def __call__(self, request):
        ip = self.get_client_ip(request)
        now = time.time()
        last_visit_time = self.limits.get(ip, 0)
        if now - last_visit_time < 1:
            return HttpResponseForbidden('您访问过于频繁,请稍后再试。')
        self.limits[ip] = now
        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

上面代码中,自定义中间件 RateLimitMiddleware 记录了各个用户的最近一次访问时间,如果与当前时间的时间差小于 1 秒,则返回一个 403 Forbidden 的响应即可。

值得注意的是,这个方法获取 IP 的方式,因网络架构的不同,可能无法获取到用户真实 IP。但是我们可以通过 Nginx 的 proxy_set_header 指令来弥补,具体可参考资料。

5. 总结

本文简单介绍了 Django 中间件的基本结构和配置方法,并提供了两个常用的示例说明,分别用于处理请求头和限制访问频率。中间件是 Django 一种强大的可插拔机制,可以用于丰富项目功能,并提高代码的可读性。

本文链接:http://task.lmcjl.com/news/14309.html

展开阅读全文