中间件
简介
中间件的本质就是一个python 类,中间件的本质是一个python类实现的装饰器,装饰器分为两种一种为函数实现,另一种为类实现,装饰器详情见:https://www.cnblogs.com/arvin-feng/p/11108799.html
中间件:是一个轻量级的,底层的插件,可以介入Django的请求和相应过程(面向切面编程)
面向切面编程(AOP)
面向切面编程(Aspect Oriented Programming)简称AOP。AOP的主要实现目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合的隔离效果。
面向切面编程有两个核心概念,1是切点,切面,也就是在哪切 2是通过切面可以获得什么
中间件的可切入点:
如图中红字所示,python在四个位置上内置了切点,我们除了关注这些切点,还要关注这些切面里面有什么
切入函数
__init__:
没有参数,服务器响应第一个请求的时候自动调用,用户确定是否启用该中间件process_request(self,request):
在执行视图前被调用,每个请求上都会调用,不主动进行返回或返回HttpResponse对象- 不主动进行返回指的是返回值为none,这样会继续执行后续的视图操作,而返回HttpResponse则是将这里切面切开。
- 我们在处理之前通过这个切面可以做一遍校验,检查request请求和不和规,如果不合格,直接拒绝。
process_view(self,request, callback, callback_args, callback_kwargs):
调用视图之前执行,每个请求都会调用,不主动进行返回或返回HttpResponse对象process_template_response(self,request,response):
在视图刚好执行完后进行调用,每个请求都会调用,不主动进行返回或返回HttpResponse对象process_response(self,request,response):
所有响应返回浏览器之前调用,每个请求都会调用,不主动进行返回或返回HttpResponse对象process_exception(self,request,exception):
当视图抛出异常时调用,不主动进行返回或返回HttpResponse对象- 视图出错就会报出5xx服务器内部错误,这种错误是程序员最丢人的错误,通过这个切面我们可以全局捕获5xx错误,提高容错率。
中间件功能
实现统计功能
- 统计IP
- 统计浏览器,使用IE还是谷歌浏览器
实现权重控制
- 黑名单
- 白名单
- 权限设计
实现反爬
反爬虫
- 十秒之内只能搜索一次
- 实现频率控制(淘宝刷新30次就会出题目证明你是个人)
实验:自定义中间件 process_request
前面的概念看了很懵批,莫慌,看看下面的实验,搞不好就能顿悟。
自定义中间件流程
- 在工程目录下创建middleware目录
目录中创建一个python文件
- 中间件是一个python文件
- 在python文件中导入中间件的基类
from django.utils.deprecation import MiddlewareMixin
- 在类中根据功能需求,创建切入需求类,重写切入点方法(自定义的中间件系统不承认,需要伪装成中间件,所以需要继承自系统中间件)
class LearnAOP(MiddlewareMixin):
def process_request(self,request):
print('request的路径',request.GET.path)
- 启用中间件,在settings中进行配置,MIDDLEWARE中添加
middleware.文件名.类名
实验1
1./2. 创建目录,创建python文件
3.
在新建的py文件中添加类来继承系统的中间件
from django.utils.deprecation import MiddlewareMixin
class HelloMiddle(MiddlewareMixin): # Mixin 是使混合的意思,代表基类,多继承时一般以mixin结尾
pass
4.
注册settings,找到middleware,添加:
MIDDLEWARE = [
'middleware.LearnMiddle.HelloMiddle', # .指的是路径的"/",目录,文件名.类
'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',
]
5.写切点,获取切面
我们将刚才新建的类补全
from django.utils.deprecation import MiddlewareMixin
class HelloMiddle(MiddlewareMixin): # Mixin 是使混合的意思
def process_request(self, request):
print(request.META.get('REMOTE_ADDR'))# 用来获得访问者的ip地址
6.新建路由页面测试中间件
urls:
url('^home/', views.home, name='home'),
views:
def home(request):
return HttpResponse('HOME')
我们访问home
接着我们看到了IP地址,这样我们就可以进行数据分析,根据各种IP地址分析爱上这个网站的都是哪个区域的人,哪个国家的人,哪个城市等等等等
实验2
做一个抢手机的网站,抢优惠券的时候电脑评估你的个人信息,有可能觉得你不是优质客户,所以别人能抢到而你却抢不到.
1.新建url:
url('^getphone/', views.get_phone, name='get_phone'),
2.新建views
def get_phone(request):
if random.randrange(100) > 95:
return HttpResponse('恭喜你抢到小米10pro')
return HttpResponse('不好意思正在排队嗷')
3.访问网页
3.添加中间件
我们不对ivews做任何修改,而是通过中间件来实现抢手机的概率想要多少就是多少。
修改LearnMiddleware.py文件:
(白名单)
class HelloMiddle(MiddlewareMixin): # Mixin 是使混合的意思
def process_request(self, request):
print(request.META.get('REMOTE_ADDR'))
ip = request.META.get('REMOTE_ADDR')
if ip == '127.0.0.1':
return HttpResponse('恭喜你免费获得小米10pro')
可以看到一定中奖
我也可以避嫌,给自己一个加权权重
if request.path == '/app/getphone/':
if ip == '127.0.0.1':
if random.randrange(100) > 20:
return HttpResponse('恭喜你免费获得小米10pro')
这样就可以让自己变成80%+(0.2*0.05)的中奖概率,而其他人只有5%
实验3
现在有个撸羊毛的家伙顾某,此人酷爱上京东撸羊毛,今天买了个电脑玩了6天(7天无理由退款)给退货了,明天又买了张显卡挖两天框矿就退货,此后总是买了退,这人就不能让他拿到满100减99元的优惠券,我们就要拉进黑名单。
urls:
url('^getticket/', views.get_ticket, name='get_ticket'),
views:
def get_ticket(request):
return HttpResponse('已抢到优惠券')
LearnMiddleware.py:
(黑名单)
if request.path == '/App/getticket/':
if ip.startswith('192.168.1.1'): # 以结尾1开头的ip地址都显示被抢光
return HttpResponse('已抢光')
这样就拉入了黑名单
实验二实验三体现了权重控制
实验4
我们要限制下载的频率,间隔10秒
urls:
url('^search/', views.search, name='search'),
views:
def search(request):
return HttpResponse('搜索到的种子资源')
想要修改频率,我们可以在views函数中修改,但是不提倡
因为程序讲究低耦合,搜索功能就是单纯的搜索,但是还有一些功能的比如频率限制,这两个功能要区分开,不能混和写,这两个功能应该是独立的,通过某种方式,将二者组合在一起
LearnMiddleware.py:
if request.path == '/App/search/':
result = cache.get(ip) # 这里获取缓存中的ip地址
if result: # 如果缓存存在这个IP地址,就会频繁
return HttpResponse('您访问的太频繁,请稍后再访问')
cache.set(ip, ip, timeout=10) # 如果缓存没有就需要保存ip地址10s
此处评论已关闭