DRF权限&DRF频率

DRF权限组件源码

与之前的版本组件, 认证组件一样从dispatch分发之前的initial开始

进入到check_permissions(request)中,看看

接着进入get_permissions()中查看干了个啥?

这个permission_classes与之前的版本类似, 都是通过获取settings中的配置, 赋值给permission_classes.不同之处,在于版本是多了一步先通过Request.user的方法改变了self的调用者的身份.权限并没有, 就是视图调用.

点击进入api_settins

点击进入DEFAULT,这里是一些settings(DRF)的默认配置

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

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

AllowAny(BasePermission):

  def has_permission(self, request, view):

    return True

这个是默认的配置的认证类, 我们可以看到一定要有has_permission方法, 返回True代表所有人都有权限.

权限的详细用法

Python的代码是一行一行执行的那么, initial方法初始化这些组件的时候~~

也是顺序的~~

我们的版本在前面, 然后是认证, 然后是权限, 最后是频率~所以

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

from rest_framework.permissions import BasePermission


class MyPermission(BasePermission):
    message = "VIP用户才能访问"

    def has_permission(self, request, view):
        """
        自定义权限只有vip用户访问
        注意我们初始化时候的顺序是从认证权限前面的, 所以只要认证通过~
        我们这里就可以通过request.user拿到我们的用户信息
        :param request:
        :param view:
        :return:
        """
        if request.user and request.user.type == 1:
            return True
        else:
            return False
第一步:写权限类
class TestAuthView(APIView):
    authentication_classes = [MyAuth, ]
    permission_classes = [MyPermission, ]

    def get(self, request, *args, **kwargs):
        print(request.user)
        print(request.auth)
        username = request.user
        return Response(username)
局部注册
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"]
}
全局注册

 

DRF的频率

频率限制是做什么的

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

我们的DRF提供了一些频率限制的方法

频率组件源码

版本, 认证, 权限, 频率这几个组件的源码是一个流程,

频率组件的原理

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

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

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

{IP1: {"第三次访问的时间", "第二次访问的时间", "第一次访问的时间"}}

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

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

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

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

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

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

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

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

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

频率组件的详细用法

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

VISIT_RECORD = {}
class MyThrottle(object):

    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        """
        自定义频率限制60秒内只能访问三次
        """
        # 获取用户IP
        ip = request.META.get("REMOTE_ADDR")
        timestamp = time.time()
        if ip not in VISIT_RECORD:
            VISIT_RECORD[ip] = [timestamp, ]
            return True
        history = VISIT_RECORD[ip]
        self.history = history
        history.insert(0, timestamp)
        while history and history[-1] < timestamp - 60:
            history.pop()
        if len(history) > 3:
            return False
        else:
            return True

    def wait(self):
        """
        限制时间还剩多少
        """
        timestamp = time.time()
        return 60 - (timestamp - self.history[-1])
自定义频率限制

配置自定义频率限制类

REST_FRAMEWORK = {
    # ......
    # 频率限制的配置
    "DEFAULT_THROTTLE_CLASSES": ["Throttle.throttle.MyThrottle"],
    }
}
View Code

使用自带的频率限制类

from rest_framework.throttling import SimpleRateThrottle

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_THROTTLE_CLASSES": ["Throttle.throttle.MyVisitThrottle"],
    "DEFAULT_THROTTLE_CLASSES": ["Throttle.throttle.MyThrottle"],
    "DEFAULT_THROTTLE_RATES":{
        'WD':'5/m',         #速率配置每分钟不能超过5次访问,WD是scope定义的值,

    }
}

 

频率限制的源码分析

"DEFAULT_THROTTLE_CLASSES": ["Throttle.throttle.MyThrottle"],

 

 

posted @ 2018-11-01 17:04  猴里吧唧  阅读(161)  评论(0)    收藏  举报