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类型
  • 相关阅读:
    深度学习 框架比较
    深度学习 Fine-tune 技巧总结
    基于Spark环境对比Python和Scala语言利弊
    【Python系列】HDF5文件介绍
    【Git】CentOS7 通过源码安装Git
    【Git】Git工具常用命令
    登录自动跳转
    offset,scroll,client系列
    谷歌浏览器input中的text 和 button 水平对齐的问题
    git 的基本使用
  • 原文地址:https://www.cnblogs.com/zhuchunyu/p/10021978.html
Copyright © 2011-2022 走看看