django-基于中间件写一个限制频繁登录前端
额额,标题已经很醒目了,经过中间件去实现,其余方法也能够实现python
浏览器前端传来的请求,必须经过中间件,才能到后面路由,视图函数,因此咱们在中间件那里作一层处理,
咱们还须要知道是哪一个ip,在何时,请求了几回,这些数据是要知道,而且记录下来,因此我建立了一个
表,来存放这些信息数据数据库
models文件:django
class Host_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文件(我自定义的中间件):app
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render, HttpResponse from app01 import models import datetime class Md1(MiddlewareMixin): def process_request(self, request): url = request.path if url.startswith('/favicon.ico'): return HttpResponse class Md2(MiddlewareMixin): def process_request(self, request): now_time = datetime.datetime.now() host = request.META.get('REMOTE_ADDR') ret = models.Host_info.objects.filter(host=host).first() if ret: aa = now_time - ret.start_time if aa.seconds >= 60: ret.count = 1 ret.start_time = now_time ret.is_lock = '2' ret.save() return None if aa.seconds < 60 and ret.is_lock == '1': return HttpResponse('登录次数频繁,一分钟后再试') if ret.count < 4 and ret.is_lock == '2': if ret.count == 2: ret.is_lock = '1' ret.count = 0 ret.save() else: ret.count += 1 ret.start_time = now_time ret.save() return None else: models.Host_info.objects.create(host=host, start_time=now_time, count=1) return None
settings文件:
添加两行代码在MIDDLEWARE列表中:
'mymiddleware.Md1',
'mymiddleware.Md2',函数
并配置下面两句,缘由后面会说
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = False测试
遇到两个问题:url
问题一:就是datetime,也就是时间分区问题,由于我数据表中须要保存到该ip访问的时间,存的时候存的是datetime对象
,可是我从数据库中取出来这个时间,进行比较会报出错误,错误类型忘记了,我就打印了从数据库中取出的时间数据,
发现,这个时间带着时区,而我datetime.datetime.now()的时间是本机时间,根本不能相减,相比较。网上收索才
知道django默认是有时间分区的,TIME_ZONE = 'UTC',USE_TZ = True,这两句。
解决方式:在setting文件中将上面那两句修改成TIME_ZONE = 'Asia/Shanghai',USE_TZ = False。这样就解决了。
在django中但凡出现时间的话,这个地方须要注意下。code
问题二:额额这个问题,我在写的时候出现过,可是今天测试没那个问题,反正写上吧。我以前的错误就是我发出一个请求,首先
第一个请求就是访问到url,接着第二个请求就是发出favicon.ico这种相似的,请求ico这个。以这个状况来讲问题吧,
你虽然在浏览器只发出一个请求,可是响应过来的网页,里面能够还有其余请求,因此这中状况须要考虑到。
解决方式:我在对用户ip作限制以前,加一个中间件,过滤掉其它的请求。,也就是上面的MD1。
补充·
补充一点,datetime的一个用法 例子中我用到datetime对象之间相减,取差多少秒,也就是这句 aa = now_time - ret.start_time aa.seconds # 取到相差多少秒 这里的aa是datetime.timedelta类型