• Django Rest Framework --用户访问频率限制


    自定义访问频率控制类结构

    views.py

    from rest_framework.throttling import BaseThrottle
    import time
    # 节流
    visit_dict={}
    
    class Visitthrottle(BaseThrottle):
        #通过IP做唯一标识符
        #问题:非登陆用户一分钟内只允许访问3次
        def __init__(self):
            self.history=None
    
        def allow_request(self,request, view):
            #获取IP地址
            remote_addr = self.get_ident(request)
            ctime=time.time()
            if remote_addr not in visit_dict:
                visit_dict[remote_addr]=[ctime,]
                return True
            self.history = visit_dict.get(remote_addr)
            while self.history and self.history[-1] <ctime - 60:
                self.history.pop()
            if len(self.history)<3:
                self.history.insert(0,ctime)
                return True
    
        def wait(self):
            ctime=time.time()
            return 60-(ctime-self.history[-1])
    class TestThrottle(APIView):
        throttle_classes = [VisitThrottle,]
         
        def get(self, request, *args, **kwargs):
            pass
            '''
            等等一系列的视图功能方法
            '''

    实现原理分析:

    • 需要使用用户IP地址作为唯一标识符,如果使用用户登陆账号作为唯一标识符,一个用户可能拥有多个账号,则达不到节流的目的,但使用IP地址也不是说一定不能改变,但相比于登陆账号,使用IP地址更能达到节流的作用。
    •  以IP地址作为KEY键,多个访问时间形参列表作为value存入字典中,用户每次访问读取字典,判断最后一次访问时间与这次访问时间相差时间,相差时间大于60秒,删除时间列表中最后元素,然后判断列表长度是否小于3,如果小于3,表示一分钟内未访问3次,允许继续访问。
    • 如果不允许访问,会执行wait函数,返回需要等待时间。
    • 但是在项目开发中不使用自定义节流类,是因为drf中已经实现了节流方法。内置接口代码基本结构,内置节流类的实现原理与自定义节流类原理相同。

    内置节流类结构

    settings.py:

    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_CLASSES':['api.utils.mythrottle.UserThrottle',]
        'DEFAULT_THROTTLE_RATES': {
            '未认证用户': '10/m',
            '已认证用户': '100/h',
        },
    }
    

    mythrottle.py:

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import exceptions
    from rest_framework.throttling import SimpleRateThrottle
     
     
    class VisitThrottle(SimpleRateThrottle):
        scope = "未认证用户"
     
        def get_cache_key(self, request, view):
            return  self.get_ident(request)
           
     
    class UserThrottle(SimpleRateThrottle):
        scope = "已认证用户"
     
        def get_cache_key(self, request, view):
            return  request.user  # 认证通过后,认证方法authenticate的返回值之一<br><br>
    
    
    class TestThrottle(APIView):<br>  # 这样设置后,节流功能就会使用VisitThrottle类,而不会使用UserThrottle类
        throttle_classes = [VisitThrottle,]
         
        def get(self, request, *args, **kwargs):
            pass
            '''
            等等一系列的视图功能方法
            '''
    

      这里使用的节流类是继承了SimplePateThrottle类,而这个类利用了django内置的缓存来存储访问记录。通过全局节流设置,所有的视图类默认是使用UserThrottle类进行节流,如果不想使用默认的类就自定义给throttle_classes属性变量赋值,如:“throttle_classes = [VisitThrottle,]”。看到内置节流类的使用,可能一脸懵逼,下面进行源码分析。

    源码分析

    与之前认证权限控制的源码分析方法一致,先进入函数入口dispatch方法,封装完新的request对象后,进入initialize_request方法,我们会发现还有一个函数调用我们没有分析,所以这就是我们的节流函数。

    1.为什么会使用scope属性变量,有什么用?

    进入check_throttles函数,是否觉得很熟悉?没错在get_throttles方法中肯定也是一个列表生产式,返回一个有节流类实例组成的列表。

      

     在列表生成式中,先对内置类SimplePateThrottle进行实例化,在实例化中去拿到scope的值,并且根据值作为key值去配置文件中拿到对应value值。在parse_rate方法中可以看出value是又‘/’分隔的一个字符串。

      

    2.为什么会使用‘get_cache_key’方法,该方法的返回值是什么?

    实例化完成后,执行allow_request方法,首先执行的是get_cache_key’方法

     

    在get_cache_key’方法中里面什么都没写,所以就是说我们在使用内置节流类时,必须重构get_cacha_key方法,否则会抛出异常,因为内置节流类是通过django缓存实现,所以需要给它一个唯一标识符,在这里我选择的是选择用户的IP地址进行唯一确认,所以这里的返回值为一个唯一标识符。

     

    接下来的操作与我们自定义节流类的原理一致。最后如果返回false,调用wait方法,抛出异常

    3.为什么使用‘throttle_classes’属性变量,它有什么用?

    get_throttles方法返回的是一个列表生成式,而这里的throttle_classes就是在视图类TestThrottle中使用的,该变量就保存节流类对象。

     4.‘DEFAULT_THROTTLE_CLASSES’从那里来,有什么用?

    通过throttle_classes属性变量,跳转到该图,可以看到配置文件中说的“DEFAULT_THROTTLE_CLASSES”,它是用来通过配置文件settings来对全局节流类进行配置,功能等价于throttle_classes属性变量。

     5.‘DEFAULT_THROTTLE_RATES’从那里来,有什么用?

    由SimpleRateThrottle类和上文对scope属性变量的分析可知,DEFAULT_THROTTLE_RATES就是为了存储在配置文件中设置的不同的节流方法的。

     

    综上所述,可以看出,在利用内置节流接口时,通过配置文件settings的设置和提供该接口所需的用户唯一标识外,不需要我们做再多的操作,这就形成了我们上文写的内置接口代码基本结构的样式。

  • 相关阅读:
    git-format-patch如何指定补丁生成的Subject格式
    openwrt生成的交叉编译器在哪里
    git如何在自动生成补丁时指定补丁名的起始编号
    hyper-v安装虚拟机ubuntu 18.04 64bit后无法使能增强模式怎么办
    Best regards缩写是什么
    git如何自动打补丁
    ubuntu 18.04 64bit build tensorflow report error:C++ compilation of rule '//tensorflow/core/kernels:broadcast_to_op' failed (Exit 4)
    linux安装yaml时出现Could not find a version that satisfies the requirement yaml (from versions: ) No matching distribution found for yaml
    String.format保留小数位数
    BigDecimal的保留位数和四舍五入的方法
  • 原文地址:https://www.cnblogs.com/kxsph/p/10572147.html
Copyright © 2020-2023  润新知