django 基于中间件实现限制ip频繁访问过程详解
额额,标题已经很醒目了,通过中间件去实现,其他方法也可以实现
浏览器前端传来的请求,必须通过中间件,才能到后面路由,视图函数,所以我们在中间件那里做一层处理,我们还需要知道是哪个ip,在什么时候,请求了几次,这些数据是要知道,并且记录下来,所以我创建了一个表,来存放这些信息数据
models文件:
classHost_info(models.Model): host=models.CharField(max_length=32) count=models.IntegerField() start_time=models.DateTimeField() is_lock=models.CharField(max_length=32,default='2')
host:记录主机ip
count:记录请求的次数
start_time:记录请求的时间
is_lock:记录该ip的状态,默认为2 2代表未锁定,1代表锁定
接下来就是自定义中间件了,并写process_request方法,我们只对请求做处理,我先贴代码,最后写我遇到的一些问题
mymiddleware文件(我自定义的中间件):
fromdjango.utils.deprecationimportMiddlewareMixin fromdjango.shortcutsimportrender,HttpResponse fromapp01importmodels importdatetime classMd1(MiddlewareMixin): defprocess_request(self,request): url=request.path ifurl.startswith('/favicon.ico'): returnHttpResponse classMd2(MiddlewareMixin): defprocess_request(self,request): now_time=datetime.datetime.now() host=request.META.get('REMOTE_ADDR') ret=models.Host_info.objects.filter(host=host).first() ifret: aa=now_time-ret.start_time ifaa.seconds>=60: ret.count=1 ret.start_time=now_time ret.is_lock='2' ret.save() returnNone ifaa.seconds<60andret.is_lock=='1': returnHttpResponse('登陆次数频繁,一分钟后再试') ifret.count<4andret.is_lock=='2': ifret.count==2: ret.is_lock='1' ret.count=0 ret.save() else: ret.count+=1 ret.start_time=now_time ret.save() returnNone else: models.Host_info.objects.create(host=host,start_time=now_time,count=1) returnNone
settings文件:
添加两行代码在MIDDLEWARE列表中:
'mymiddleware.Md1', 'mymiddleware.Md2',
并配置下面两句,原因后面会说
TIME_ZONE='Asia/Shanghai' USE_TZ=False
遇到两个问题:
问题一:就是datetime,也就是时间分区问题,因为我数据表中需要保存到该ip访问的时间,存的时候存的是datetime对象,但是我从数据库中取出来这个时间,进行比较会报出错误,错误类型忘记了,我就打印了从数据库中取出的时间数据, 发现,这个时间带着时区,而我datetime.datetime.now()的时间是本机时间,根本不能相减,相比较。
网上收索才 知道django默认是有时间分区的,TIME_ZONE='UTC',USE_TZ=True,这两句。
解决方式:在setting文件中将上面那两句修改为TIME_ZONE='Asia/Shanghai',USE_TZ=False。这样就解决了。
在django中但凡出现时间的话,这个地方需要注意下。
问题二:额额这个问题,我在写的时候出现过,但是今天测试没那个问题,反正写上吧。我之前的错误就是我发出一个请求,
首先
第一个请求就是访问到url,接着第二个请求就是发出favicon.ico这种类似的,请求ico这个。以这个情况来说问题吧,
你虽然在浏览器只发出一个请求,但是响应过来的网页,里面可以还有其他请求,所以这中情况需要考虑到。
解决方式:我在对用户ip做限制之前,加一个中间件,过滤掉其它的请求。,也就是上面的MD1。
##代码其实很简单,主要是逻辑处理,你是怎么想就用代码去实现。 ##对了,这里的数据存储,你可以定义一个变量去存放存这些信息(也就是我数据表存放的这个) ##这里唯一值得注意的就是时间了,你要很清楚知道时区这个问题。
补充一点,datetime的一个用法
例子中我用到datetime对象之间相减,取差多少秒,也就是这句
aa=now_time-ret.start_time aa.seconds#取到相差多少秒
这里的aa是datetime.timedelta类型
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。