自定义节流的方法 ,限制60s内只能访问3次
from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
import time
class ThrottleAuth(BaseThrottle):
# 声明一个字典,用于保存不同用户的访问时间。
visit_dict = {}
def __init__(self):
# visit_historys该变量就是用来记录用户每次的访问时间。
self.visit_historys = []
def allow_request(self, request, view):
"""
认证用户是否能够向这个API接口发起请求。返回值是True,就可以访问;反之,就不能访问;
:param request:
:param view:
:return:
"""
# 1. 先从请求中获取对方的IP地址;
IP = request.META.get('REMOTE_ADDR')
# 2. 获取当前用户向API接口发送请求的时间
current_time = time.time()
if IP not in self.visit_dict:
# 3. 如果获取的当前IP,在self.visit_dict字典中不存在,说明这个IP地址是第一次访问。
self.visit_dict[IP] = [current_time]
# 此时返回True,访问次数不够,可以继续访问。
return True
# 4. 如果这一次的IP在记录中已经存在了,说明不是第一次访问,和第一次访问的时间进行对比。
# 获取IP对应的时间列表
history = self.visit_dict.get(IP)
self.visit_historys = history
while history and history[-1] < current_time - 60:
# 当前时间-60s 大于 第一次访问的时间,说明这一次的访问和上一次的访问时间不在1分钟之内。
# 将列表中的[-1]对应的数据删除
history.pop()
# 5. 经过上述循环之后,列表中剩余的都是1分钟之内的时间了。
if len(history) < 5:
# 可以访问,1分钟之内访问没有超过5次。
history.insert(0, current_time)
return True
# 6. 当前访问总次数 >= 5次,不能再访问这个接口了。
return False
#全局
REST_FRAMEWORK = {
#节流
"DEFAULT_THROTTLE_CLASSES":['API.utils.throttle.VisitThrottle'],
}
源码分析
dispatch()->initial()
check_throttles()
allow_request():
返回值True/False
内置节流类
SimpleRateThrottle
get_ident也是获取ip
class IPThrottle(SimpleRateThrottle):
"""
对于匿名用户的控制
使用throttling.py中的内置的访问控制类来实现API的访问控制。
"""
scope = 'IP'
def get_cache_key(self, request, view):
return request.META.get('REMOTE_ADDR')
class UserThrottle(SimpleRateThrottle):
"""
对于已登录用户的控制
使用throttling.py中的内置的访问控制类来实现API的访问控制。
"""
scope = 'USER'
def get_cache_key(self, request, view):
return request.user.username
# 配置自定义的访问控制类
'DEFAULT_THROTTLE_CLASSES': ['utils.base_authenticate.IPThrottle'],
# 使用Throttle内置的访问控制类
'DEFAULT_THROTTLE_RATES': {
'IP': '3/m', # 'IP'就是源码中的scope, '3/m'就是源码中的rate。
'USER': '10/m', # 'USER'就是源码中的scope, '10/m'就是源码中的rate。
},