zoukankan      html  css  js  c++  java
  • drf6 权限和频率控制组件

    对某件事情决策的范围和程度,我们叫做权限,权限是我们在项目开发中非常常用到的。

    DRF框架给我们提供的权限组件

    权限组件

     

    之前DRF的版本和认证,知道了权限和频率跟版本认证都是在initial方法里初始化的

    权限类一定要有has_permission方法~否则就会抛出异常~~这也是框架给我提供的钩子~~

    我们先看到在rest_framework.permissions这个文件中~存放了框架给我们提供的所有权限的方法~~

    权限的用法

    版本-> 认证-> 权限 –> 频率

    执行initial方法初始化这些组件的时候,是有顺序的,我们的版本在前面,然后是认证,然后是权限,最后是频率

    我们的权限执行的时候,我们的认证已经执行结束了。

    前提在model中的UserInfo表中加了一个字段用户类型的字段

    权限控制类,根据request 中数据处理权限

    utils/permission.py

    from rest_framework.permissions import BasePermission
    
    class MyPermission(BasePermission):
        message = "您没有权限"
    
        def has_permission(self, request, view):
            # 判断用户是否有权限
            user_obj = request.user
            if user_obj.type == 3:
                return False
            else:
                return True
    
    第一步 写权限类
    from utils.auth import MyAuth
    from utils.permission import MyPermission
    class TestView(APIView):
        authentication_classes = [MyAuth,]  # 先登录,再判断权限
        permission_classes = [MyPermission, ]  # 指明权限控制类
    
        def get(self, request):
            print(request.user)
            print(request.auth)
            user_id = request.user.id
            return Response("认证测试")
    
    
    局部视图注册 authDemo/views.py
    REST_FRAMEWORK = {
        # 默认使用的版本控制类
        'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
        # 允许的版本
        'ALLOWED_VERSIONS': ['v1', 'v2'],
        # 版本使用的参数名称
        'VERSION_PARAM': 'version',
        # 默认使用的版本
        'DEFAULT_VERSION': 'v1',
        # 配置全局认证
        # 'DEFAULT_AUTHENTICATION_CLASSES': ["BRQP.utils.MyAuth", ]
        # 配置全局权限
        "DEFAULT_PERMISSION_CLASSES": ["BROP.utils.MyPermission"]
    }
    
    
    全局注册 settings.py

    image

    频率控制

    开放平台的API接口调用需要限制其频率,以节约服务器资源和避免恶意的频繁调用。

    我们的DRF提供了一些频率限制的方法,我们看一下。

     

    频率组件原理

    DRF中的频率控制基本原理是基于访问次数和时间的,当然我们可以通过自己定义的方法来实现。

    当我们请求进来,走到我们频率组件的时候,DRF内部会有一个字典来记录访问者的IP,

    以这个访问者的IP为key,value为一个列表,存放访问者每次访问的时间,

    {  IP1: [第三次访问时间,第二次访问时间,第一次访问时间],}

    把每次访问最新时间放入列表的最前面,记录这样一个数据结构后,通过什么方式限流呢

    如果我们设置的是10秒内只能访问5次,

      -- 1,判断访问者的IP是否在这个请求IP的字典里

      -- 2,保证这个列表里都是最近10秒内的访问的时间

          判断当前请求时间和列表里最早的(也就是最后的)请求时间的查

          如果差大于10秒,说明请求以及不是最近10秒内的,删除掉,

          继续判断倒数第二个,直到差值小于10秒

      -- 3,判断列表的长度(即访问次数),是否大于我们设置的5次,

          如果大于就限流,否则放行,并把时间放入列表的最前面。

    频率组件的详细用法

    频率组件的配置方式其实跟上面的组件都一样,我们看下频率组件的使用。

    单位时间段内限制IP的访问次数

    60s内访问不得大于3次

    from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
    import time
    
    VISIT_RECORD = {}   # ip地址字典
    
    
    class MyThrottle(BaseThrottle):
    
        def __init__(self):
            self.history = None
    
        def allow_request(self, request, view):
            # 实现限流的逻辑
            # 以IP限流
            # 访问列表 {IP: [time1, time2, time3]}
            # 1, 获取请求的IP地址
            ip = request.META.get("REMOTE_ADDR")
            # 2,判断IP地址是否在访问列表
            now = time.time()
            if ip not in VISIT_RECORD:
                # --1, 不在 需要给访问列表添加key,value
                VISIT_RECORD[ip] = [now,]
                return True
                # --2 在 需要把这个IP的访问记录 把当前时间加入到列表
            history = VISIT_RECORD[ip]
            history.insert(0, now)
            # 3, 确保列表里最新访问时间以及最老的访问时间差 是1分钟
            while history and history[0] - history[-1] > 60:
                history.pop()
            self.history = history  # 更新访问列表
            print(history,print(VISIT_RECORD[ip]))
            # 4,得到列表长度,判断是否是允许的次数。      60s秒内不得超过三次请求
            if len(history) > 3:
                return False
            else:
                return True
    
        def wait(self):
            # 返回需要再等多久才能访问
            time = 60 - (self.history[0] - self.history[-1])
            return time
    
    自定义的频率限制类
    REST_FRAMEWORK = {
        # ......
        # 频率限制的配置
        "DEFAULT_THROTTLE_CLASSES": ["Throttle.throttle.MyThrottle"],
        }
    }
    配置自定义频率限制
    class TestView(APIView):
        authentication_classes = [MyAuth,]
        permission_classes = [MyPermission, ]
        throttle_classes = [MyThrottle, ]
    
        def get(self, request):
            print(request.META)
            print(request.user)
            print(request.auth)
            user_id = request.user.id
            return Response("认证测试")
    使用自定义频率限制

    image_thumb4_thumb

    框架实现的限流类

    from rest_framework.throttling import SimpleRateThrottle
    
    
    class MyVisitThrottle(SimpleRateThrottle):
        scope = "WD"
    
        def get_cache_key(self, request, view):
            return self.get_ident(request)
    
    
    使用框架自带的频率限制类

    配置

    REST_FRAMEWORK = {
        # "DEFAULT_VERSIONING_CLASS": "utils.version.MyVersion",
        "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.QueryParameterVersioning",
        "DEFAULT_VERSION": "v1",
        "ALLOWED_VERSIONS": "v1, v2",
        "VERSION_PARAM": "ver",
        # "DEFAULT_AUTHENTICATION_CLASSES": ["utils.auth.MyAuth", ],
        "DEFAULT_THROTTLE_RATES": {
            "WD": "3/m"  # 一分钟三次
        }
    }
    
    

    6

  • 相关阅读:
    Java实现 LeetCode 735 行星碰撞(栈)
    Java实现 LeetCode 735 行星碰撞(栈)
    Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)
    Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)
    Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)
    Java实现 蓝桥杯算法提高 求最大值
    Java实现 蓝桥杯算法提高 求最大值
    Java实现 蓝桥杯算法提高 求最大值
    Python eval() 函数
    Python repr() 函数
  • 原文地址:https://www.cnblogs.com/wenyule/p/10462705.html
Copyright © 2011-2022 走看看