您的位置:首页 > 其它

drf 访问频率限制

2020-11-01 20:37 971 查看

频率限制

   一个网站的访问频率限制是非常重要的,访问频率限制做的好可以预防爬虫等恶意行为。

   使用

drf
的频率限制对网站接口访问做出限制十分的便捷好用,你只需要直接进行配置即可。

内置限制

局部使用

   首先我们在视图中进行配置:

from rest_framework.throttling import UserRateThrottle  # 已登录的
from rest_framework.throttling import AnonRateThrottle  # 未登录的
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from django.contrib import auth

class ThrottleTestAPI(GenericAPIView):
throttle_classes = [UserRateThrottle,AnonRateThrottle]

def get(self,request):
if request.user.is_authenticated:  # 用户一登陆
return Response(data="你的请求次数有十次每分钟")
return Response("你的请求次数只有三次每分钟")

def post(self,request):
user_obj = auth.authenticate(username="admin",password="admin123")
auth.login(request,user_obj)
return Response("登录成功了")

   其次,针对已登录的用户和未登录的用户,可以在

settings
中进行配置限制次数:

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {  # 限制次数 , 未登录用户一分钟最多三次,登录用户最多一分钟十次
'anon': '3/m',  # 会去配置的 UserRateThrottle 以及 AnonRateThrottle 中找到属性 scope ,scope对应的就是生效的配置
'user': '10/m'
}
}

全局使用

   如果全局使用,则可以进行如下配置:

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {  # 限制次数 , 未登录用户一分钟最多三次,登录用户最多一分钟十次
'anon': '3/m',  # 会去配置的 UserRateThrottle 以及 AnonRateThrottle 中找到属性 scope ,scope对应的就是生效的配置
'user': '10/m'
}
}

   如果想针对某一个视图取消全局配置,则将

throttle_classes
设置为空列表即可:

class ThrottleTestAPI(GenericAPIView):
throttle_classes = []

def get(self,request):
if request.user.is_authenticated:
return Response(data="你的请求次数有十次每分钟")
return Response("你的请求次数只有三次每分钟")

def post(self,request):
user_obj = auth.authenticate(username="admin",password="admin123")
auth.login(request,user_obj)
return Response("登录成功了")

自定制限制

频率限制原理

  

drf
中的频率控制基本原理是基于访问次数和时间的,当然我们可以通过自己定义的方法来实现。当我们请求进来,走到我们频率组件的时候,
drf
内部会有一个字典来记录访问者的IP

   以这个访问者的

IP
key
value
为一个列表,
value
里面存放访问者每次访问的时间,如下:

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

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

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

  1. 判断访问者的
    IP
    是否在这个请求
    IP
    的字典里
  1. 保证这个列表里都是最近10秒内的访问的时间。判断当前请求时间和列表里最早的(也就是最后的)请求时间的如果差大于10秒,说明请求以及不是最近10秒内的,删除掉继续判断倒数第二个,直到差值小于10秒
  1. 判断列表的长度(即访问次数),是否大于我们设置的5次,如果大于就限流,否则放行,并把时间放入列表的最前面。

自定义限制

   使用自定义限制时,需要创建一个类并且重写

allow_request()
以及
wait()
方法。

  

allow_request()
有两个额外的参数,分别是二次包装后的
request
对象,以及实例化过后的视图类本身,当频率限制通过后返回
True
,否则返回
False

  

wait()
方法是在
return False
后触发,必须返回一个
int
类型的值来回复频率限制还有多久取消。

class RequestLimit:
request_dict = {}
def __init__(self):
self.expiration = None
self.count = 3  # 设定最大访问次数
self.seconds = 10  # 设定过期时间,秒为单位

def allow_request(self, request, view):  # 自动调用该方法
# 拿出IP
ip = request.META.get("REMOTE_ADDR")
import time
current_time = time.time()
# 如果ip不在字典中,则添加即可,代表当前已访问了一次
if not ip in self.request_dict:
self.request_dict[ip] = [current_time]
return True
# 如果在,判断长度是否等于设定的最大访问次数
if len(self.request_dict[ip]) == self.count:
# 如果等于最大访问次数,则判断最后一位的时间和当前时间相差是否大于指定的过期时间
if current_time - self.request_dict[ip][-1] > self.seconds:
# 如果大于,清空写入
self.request_dict[ip].clear()
self.request_dict[ip].append(current_time)
return True
else:
# 如果不大于,说明时间还没过,暂时不能访问,设置多少秒后才能访问
self.expiration = self.request_dict[ip][-1] + self.seconds
return False
# 如果在,长度不大于3,则追加当前时间
self.request_dict[ip].append(current_time)
return True

def wait(self):
import time
current_time = time.time()
result = self.expiration - current_time  # 用过期的时间,减去当前的时间
return result

局部使用

   直接进行局部使用即可,不要再到项目全局文件夹下的

settings.py
中做额外的配置了。

class ThrottleTestAPI(GenericAPIView):
throttle_classes = [app01.app01_throttle.RequestLimit]  # 直接使用即可

def get(self,request):
return Response("get...")

f

全局使用

   全局使用也不用再规定过期时间,直接在

settings.py
中配置使用即可:

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES':['app01.app01_throttle.RequestLimit',],
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: