Django之中间件(Python)

#前言:

该博客主要讲解了在Django中,中间件的一些特点及其操作,最后会讲解如何对IP进行封禁和拉黑。后续我还会继续更新关于Python开发中的一些内容,欢迎大家关注。

一、简介:

中间件,是一种可以介入 django 的请求和响应的处理过程,能修改 django 的响应的数据。中间件提供了一种无侵入式的开发方式。

而中间件的主要作用是什么?

1、认证登录

2、统计访问量

3、拦截请求

如图所示,中间件就是可以在 django 处理视图的不同阶段进行干预。

而中间件的响应顺序:

1、请求进来的时候需要经过中间件之后才能进行路由匹配
2、响应出去的时候也需要经过中间件

二、Django 框架原先内置并启动了一些中间件:

在setting.py文件下:

MIDDLEWARE = [
# 主要对安全性的处理请求,将 http 请求重定向为 https 请求
    'django.middleware.security.SecurityMiddleware',
    
# 会话支持
    'django.contrib.sessions.middleware.SessionMiddleware',
    
# 检查是否允许浏览器访问类型 , 检查 url 是否需要添加 /
    'django.middleware.common.CommonMiddleware',
    
# 跨站点防御保护
    'django.middleware.csrf.CsrfViewMiddleware',
    
# 用户认证
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    
# Cookie 会话支持
    'django.contrib.messages.middleware.MessageMiddleware',
    
# 点击劫持保护
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

在请求处理之前,中间件根据配置文件中的中间件的配置列表从上往下依次执行

在请求处理之后,中间件根据配置文件中的中间件的配置列表从下往上依次执行

三、自定义中间件:

定义一个中间件工厂函数,返回一个可以被调用的中间件(闭包)。

中间件的工厂函数必须接收一个可以被调用的 get_response 对象请求处理。

1.在应用下新建一个 middleware.py 文件:

2.编写自定义中间件:

(具体代码的作用在注释中都有)

def simple_middleware(get_response):
    # 这里编写的代码 只在 Django 项目启动的时候被执行
    print("初始化 Django")

    def middleware(request):
        '''
        request: 和视图接收的 Request 数据是一致,都是浏览器的请求数据
        '''
        # 这里编写的代码,是在请求处理前被执行
        print('request 请求被处理前')
        response = get_response(request)
        # 这里编写的代码,是在请求处理后执行
        print('request 请求被处理后')
        return response

    return middleware

3.定义好中间件之后,需要到配置文件中的 MIDDLEWARE 列表中注册自定义中间件路径:

# 自定义中间件
'MiddlewareApp.middleware.simple_middleware',

4.最后在路由文件中和视图文件中响应中间件。

注意:

当有多个中间件同时响应的时候,如果有两个中间件,初始化是先输出后面的中间件再输出前面的,因为初始化是先访问中间件,但是输出的时候相当于要响应出去,响应出去就从后往前了。

四、自定义中间件类:

自定义中间件类需要继承 MiddlewareMixin

process_request 方法 , 是 Request 预处理函数;这个方法在请求处理之前被调用。

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render , HttpResponse

class MyMiddleware(MiddlewareMixin):

    def process_request(self , request):
        # request: 用户请求的数据
        # 可以没有返回值:None 中间件就会按照正常流程执行 ,
        # 如果配置列表中这个中间件后面还有中间件就进入到下一个中间中,否则就进入 url 请求匹配
        print("process_request 预处理函数")
        # 有返回值:HttpResponse 对象 或者其子类对象,就不执行处理其他中间件的内容,
        # 以及不进行 url 的匹配,到这里整个请求结束,然后将这个定义的返回值响应到浏览器中
        return HttpResponse('我是 process_request 响应的数据')

1.process_response 方法:

请求处理之后被调用

def process_response(self , request , response):
        '''
        :param request: 用户请求的数据
        :param response: 视图返回出来的 HttpResponse 对象
        :return: 必须要有返回值,必须返回一个 HttpResponse 对象
                可以返回视图的 response 对象
                也可以自定义的 HttpResponse 对象,则是视图中响应结果无效
        '''
        print('process_response 执行')
        # return response
        return HttpResponse('我是 process_response 响应的数据')

2.process_view 方法:

这个方法在路由匹配之后 ,视图响应之前

 def process_view(self , request , view_func , view_args , view_kwargs):
        '''
        :param request:
        :param view_func:  请求的 url 匹配到的视图函数
        :param view_args:   是给视图传递的参数
        :param view_kwargs: 是给视图传递的参数
        :return: 可以没有返回值;可以返回匹配到的视图函数,
                也可以自定义的 HttpResponse 对象,则是视图中响应结果无效
        '''
        print('process_view 执行')
        # return view_func(request)
        return HttpResponse('我是 process_view 响应的数据')

五、中间件拦截请求:

1、限制 IP 访问频率:

主题思路:
    1、获取到访问主机的 IP
    2、获取到 IP 访问的时间
    3、时间间隔:例如每四十秒访问最多15次

visit_ip = {}
class IpMiddleware(MiddlewareMixin):
    '''
    限制 IP 访问频率
    1、获取到访问主机的 IP
    2、获取到 IP 访问的时间
    3、时间间隔:40s,次数15次
    '''
    def process_request(self , request):
        # 获取用户访问的主机 IP
        ip = request.META.get('REMOTE_ADDR')
        # 获取 IP 访问的时间
        visit_time = time.time()


        # 数据保存格式:{IP:[访问时间,……],IP2:[访问时间,……]……}
        # 判断 IP 在字典中是否存在,如果存在,说明这个 IP 不是第一次访问
        # 否则 添加这个 IP 的键值对数据,是第一次访问
        if ip not in visit_ip:
            visit_ip[ip] = [visit_time]


        # IP 在字典中存在, 将访问的时间间隔大于 40s 的进行删除记录
        old_time = visit_ip.get(ip)
        for t in old_time:
            # 如果列表中获取到的时间和当前返回的时间超过 40s 则清除掉
            if visit_time - t > 40:
                old_time.remove(t)

        # 判断时间列表中记录是否有超过 15 次
        # 没有超过 , 进行记录当前的访问时间
        # 超过,限制当前 IP 访问
        if len(old_time) < 15:
            old_time.insert(0 , visit_time)
        else:
            return HttpResponse("您别累着了 , 休息一下吧!!!")

2、禁止 IP 访问:

关于禁止IP访问和上述限制IP访问就是多一层判断而已。

visit_ip = {}
black_ip = {}   # {IP:count}
class IpMiddleware(MiddlewareMixin):
    '''
    限制 IP 访问频率
    1、获取到访问主机的 IP
    2、获取到 IP 访问的时间
    3、时间间隔:40s,次数15次
    4、保存用户不良行为记录次数 , 超出 3
    '''
    def process_request(self , request):
        # 获取用户访问的主机 IP
        ip = request.META.get('REMOTE_ADDR')
        # 检查 IP 是否被拉黑
        black_num = black_ip.get(ip , 0)
        if black_num > 3:
            # IP 被拉黑 , 不允许访问
            return HttpResponse('庙小 , 容不下大佛')
        # 获取 IP 访问的时间
        visit_time = time.time()
        # 数据保存格式:{IP:[访问时间,……],IP2:[访问时间,……]……}
        # 判断 IP 在字典中是否存在,如果存在,说明这个 IP 不是第一次访问
        # 否则 添加这个 IP 的键值对数据,是第一次访问
        if ip not in visit_ip:
            visit_ip[ip] = [visit_time]

        # IP 在字典中存在, 将访问的时间间隔大于 40s 的进行删除记录
        old_time = visit_ip.get(ip)
        for t in old_time:
            # 如果列表中获取到的时间和当前返回的时间超过 40s 则清除掉
            if visit_time - t > 40:
                old_time.remove(t)

        # 判断时间列表中记录是否有超过 15 次
        # 没有超过 , 进行记录当前的访问时间
        # 超过,限制当前 IP 访问
        if len(old_time) < 5:
            old_time.insert(0 , visit_time)
        else:
            # 保存累计不良行为的次数
            black_ip[ip] = black_num + 1
            return HttpResponse("您别累着了 , 休息一下吧!!!")

注意:

我上述代码中用到的都是对字典数据进行判断,而对接到项目中时,可以对接到数据库来进行操作(与上述代码中思路一致),这样更加方便操作。

六、总结:

该博客主要讲解了在Django中,中间件的一些特点及其操作,及其如何对IP进行封禁和拉黑。欢迎大家前来指正。

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值