#前言:

该博客主要讲解了在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进行封禁和拉黑。欢迎大家前来指正。

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: