1、AOP (面向切面编程(钩子))
一个轻量级,底层的插件,可以介入Django的请求和响应过程(面向切面编程),本质上就是一个Python类
面向切面编程(Aspect Oriented Programming)简称AOP。AOP的主要实现目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合的隔离效果
在不修改原有代码的情况下,动态注入一部分代码,类似于装饰器函数
2、Django中内置的一个轻量级的切面接口
(1)、process_request
process_request(self,request)
在执行视图函数前被调用
每个请求上都会调用,不主动进行返回或返回HttpResponse对象
(2)、process_views
process_view(self,request,view_func,view_args,view_kwargs)
调用视图函数之前执行
每个请求都会调用,不主动进行返回或返回HttpResponse对象
(3)、process_template_response
process_template_response(self,request,response)
在视图函数刚好执行完后进行调用
每个请求都会调用,不主动进行返回或返回HttpResponse对象
(4)、process_response
process_response(self,request,response)
所有响应返回浏览器之前调用
每个请求都会调用,不主动进行返回或返回HttpResponse对象
(5)、process_exception
process_exception(self, request, exception)
当视图函数抛出异常时调用,不主动进行返回huo返回HttpResponse对象
3、自定义中间件
(1)、创建一个文件夹(最好放在工程根目录下)
middleware
(2)、创建一个python文件
(3)、伪装成系统的中间件,继承自MiddlewareMixin
from django.utils.deprecation import MiddlewareMixin
(4)、注册中间件
在settings中进行配置,在 MIDDLEWARE中添加,
middleware.文件名.类名
(5)、重写切点,实现自己的功能
如果我们逻辑中没有返回值,那么程序执行的时候会按照原有逻辑执行
如果我们做出了返回,那么程序将会从切点处切开,直接回到浏览器
4、实现功能
(1)、限制访问次数(10秒访问一次)
import time from django.core.cache import cache from django.http import HttpResponse from django.shortcuts import redirect from django.urls import reverse from django.utils.deprecation import MiddlewareMixin class HelloMiddle(MiddlewareMixin): def process_request(self, request): ip = request.META.get("REMOTE_ADDR") result = cache.get(ip) if result: return HttpResponse("您的访问过于频繁,请10秒之后再次搜索") cache.set(ip, ip, timeout=10)
(2)、反爬(一分钟请求10次认定爬虫)
a、普通版本
import time from django.core.cache import cache from django.http import HttpResponse from django.shortcuts import redirect from django.urls import reverse from django.utils.deprecation import MiddlewareMixin class HelloMiddle(MiddlewareMixin): def process_request(self, request): ip = request.META.get("REMOTE_ADDR") black_list = cache.get('black',[]) requests = cache.get(ip, []) while requests and time.time() - requests[-1] > 60: # 如果requests存在,并且当前时间比列表中最后一个时间大60,则弹出最后一个。(最新的数据从头部插入) requests.pop() if len(requests) > 10: # 如果访问大于十次 return HttpResponse('请求过于频繁') requests.insert(0,time.time()) cahe.set(ip, request, timeout=60)
b、升级版本
import time from django.core.cache import cache from django.http import HttpResponse from django.shortcuts import redirect from django.urls import reverse from django.utils.deprecation import MiddlewareMixin class HelloMiddle(MiddlewareMixin): def process_request(self, request): ip = request.META.get("REMOTE_ADDR") black_list = cache.get('black',[]) if ip in black_list: return HttpResponse("黑名单用户,凉凉") requests = cache.get(ip, []) while requests and time.time() - requests[-1] > 60: # 如果requests存在,并且当前时间比列表中最后一个时间大60,则弹出最后一个。(最新的数据从头部插入) requests.pop() requests.insert(0,time.time()) cahe.set(ip, requests, timeout=60) if len(requests) > 30: black_list.append(ip) cache.set('black', black_list, timeout=60*60*24) return HttpResponse("小爬虫小黑屋里呆着吧") if len(requests) > 10: # 如果访问大于十次 return HttpResponse('请求过于频繁')
5、执行顺序
中间件的配置顺序特别重要,请求按照中间件的配置顺序执行,响应按照中间件的倒序执行。