zoukankan      html  css  js  c++  java
  • django-基于中间件实现限制ip频繁访问

    ########django-基于中间件写一个限制频繁登陆########
    
    额额,标题已经很醒目了,通过中间件去实现,其他方法也可以实现
    
    浏览器前端传来的请求,必须通过中间件,才能到后面路由,视图函数,所以我们在中间件那里做一层处理,
    我们还需要知道是哪个ip,在什么时候,请求了几次,这些数据是要知道,并且记录下来,所以我创建了一个
    表,来存放这些信息数据
    
    models文件:
        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文件(我自定义的中间件):
    
        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
    
    
    遇到两个问题:
    
    问题一:就是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类型
  • 相关阅读:
    flash中网页跳转总结
    as3自定义事件
    mouseChildren启示
    flash拖动条移出flash无法拖动
    需要一个策略文件,但在加载此媒体时未设置checkPolicyFile标志
    Teach Yourself SQL in 10 Minutes
    电子书本地转换软件 Calibre
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes – Page 31 练习
  • 原文地址:https://www.cnblogs.com/zhuchunyu/p/10021978.html
Copyright © 2011-2022 走看看