drf-频率组件 权限组件

setting中的配置:

REST_FRAMEWORK = {
    # 全局使用认证组件配置
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.my_author.TokenAuth'],
    # 全局使用权限组件配置
    'DEFAULT_PERMISSION_CLASSES': ['app01.my_author.MyPermission'],
    # 全局使用频率组件配置
    'DEFAULT_THROTTLE_RATES': {
        'throttle_by_ip': '1/m',
        'anon': None,
    },
    'DEFAULT_THROTTLE_CLASSES': ['app01.my_author.MyThrottle'],
}
View Code

一、权限组件:

  针对特殊的功能只能是特殊身份的用户才能访问

1、models中的类:

class User(models.Model):
    id = models.AutoField(primary_key=True)
    user = models.CharField(max_length=20)
    password = models.CharField(max_length=20)
    choice = ((1, '超级用户'), (2, '普通用户'), (3, '黑粉用户'))
    user_type = models.IntegerField(default=2, choices=choice)  # 权限依据


class Usertoken(models.Model):
    user = models.OneToOneField(to='User', on_delete=models.CASCADE)
    token = models.CharField(max_length=64)
View Code

 2、权限判定类

from rest_framework.permissions import BasePermission

class MyPermission(BasePermission):
    def has_permission(self, request, view):
        print(request.user)
        if request.user.user_type == 1:
            return True
        else:
            self.message = '你还不是超级用户,无权限访问。当前身份%s' % request.user.get_user_type_display()
            return False
View Code

3、登录和视图类及路由同认证权限(上篇)

二、频率权限:

频率权限:控制一个用户/ip/..在一定时间内的访问次数。

频率权限实现控制的逻辑

#  老师的含有逻辑的代码

# class MyThrottling(BaseThrottle):
#     VISIT_RECORD = {}
#     def __init__(self):
#         self.history=None
#     def allow_request(self, request, view):
#         # 频率控制的逻辑
#         # 某个ip地址一分钟只能访问三次
#         # {ip地址1:[第三次访问的时间,第二次访问的时间,第一次访问的时间],ip地址2:[]}
#         # (1)取出访问者ip
#         # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
#         # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
#         # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
#         # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
#         #代码实现
#         # (1)取出访问者ip
#         # print(request.META)
#         ip = request.META.get('REMOTE_ADDR')
#         import time
#         ctime = time.time()
#         # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问
#         if ip not in self.VISIT_RECORD:
#             self.VISIT_RECORD[ip] = [ctime, ]
#             return True
#         #self.history当前访问者访问的时间列表
#         self.history = self.VISIT_RECORD.get(ip)
#         # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
#         #[1s,20s,30s]
#         while self.history and ctime - self.history[-1] > 60:
#             self.history.pop()
#         # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
#         # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
#         if len(self.history) < 3:
#             self.history.insert(0, ctime)
#             return True
#         else:
#             return False
#     def wait(self):
#         import time
#         ctime = time.time()
#         return 60 - (ctime - self.history[-1])
View Code

1、同权限组件继承BaseThrottle基类自己写的频率认证组件:

import time
from rest_framework.throttling import BaseThrottle, SimpleRateThrottle

class MyThrottle(BaseThrottle):
    list_dic = {}

    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        print(self.list_dic)
        scope = request.META.get('REMOTE_ADDR', None)
        time_ = time.time()
        if scope not in MyThrottle.list_dic:
            self.list_dic[scope] = []
            self.list_dic[scope].insert(0, time_)
            return True
        self.history = self.list_dic[scope]
        list_li = self.list_dic[scope]
        if len(list_li) < 3:
            list_li.insert(0, time_)
            return True
        first_time = list_li.pop()
        list_li.insert(0, time_)
        self.list_dic[scope] = list_li
        if time_ - first_time > 60:
            return True
        else:
            return False

    def wait(self):
        ctime = time.time()
        return 60 - (ctime - self.history[-1])
View Code

2、通过继承SimpleRateThrottle基类来实现

#drf给我们提供的频率控制类
from rest_framework.throttling import SimpleRateThrottle
class MyThrottling(SimpleRateThrottle):
    scope='throttle_by_ip'
    # 必须覆盖的方法(控制按ip、用户还是其他来限制频率的方法)
    def get_cache_key(self, request, view):
        self.get_ident(request)
        return request.META.get('REMOTE_ADDR')
View Code
原文地址:https://www.cnblogs.com/peng-zhao/p/10617007.html