节流
需求:控制用户的访问的频率(10秒中内访问三次)
思想:设立一个全局变量字典,对于匿名用户,将用户的IP作为字典的键;对于登陆用户,将用户的用户名作为字典的键。设置字典的值为一个列表,列表中存储了用户访问的时间,可以通过对列表中的时间进行操作来控制访问频率
代码实现
from django.http import JsonResponse
import time
from rest_framework.views import APIView
from api.models import UserInfo, UserToken
#可以将字典放在缓存中
VISIT_RECODE = dict()
class MyThrottles(object):
def __init__(self):
self.history = None
def allow_request(self, request, view):
# 获取用户访问的ID
remote_addr = request._request.META.get('REMOTE_ADDR')
ctime = time.time()
# 如果用户是第一次访问,将用户的IP作为字典的键,将用户的第一访问时间作为值放入字典中
if remote_addr not in VISIT_RECODE:
VISIT_RECODE[remote_addr] = [ctime, ]
# 如果用户不是第一次访问,获取列表
histiory = VISIT_RECODE.get(remote_addr)
self.history = histiory
# 筛选出10秒中列表的时间个数
while histiory and histiory[-1] < ctime - 10:
histiory.pop()
# 如果是小于3个,则可以进行访问;否则不能进行访问
if len(histiory) < 3:
histiory.insert(0, ctime)
return True # 返回True则表示可以进行访问
# return False # 返回False则表示不能进行访问
def wait(self):
ctime = time.time()
return 10-(ctime - self.history[-1])
class AuthView(APIView):
'''
用于登录认证,控制用户的访问的频率(10秒中内访问三次)
'''
authentication_classes = []
throttle_classes = [MyThrottles, ]
def post(self, request, *args, **kwargs):
ret = {'code': 1000, 'msg': None}
try:
user = request._request.POST.get('username')
password = request._request.POST.get('password')
obj = UserInfo.objects.filter(username=user, password=password).first()
# print(obj)
if not obj:
ret['code'] = 1001
ret['msg'] = '用户名或者密码错误'
# 创建token
token = md5(user)
# logging.info(token)
print(token)
UserToken.objects.update_or_create(user=obj, defaults={'token': token})
except Exception as e:
print(e)
return JsonResponse(ret)
节流的全局使用
REST_FRAMEWORK = {
#认证配置
'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.auth.MyAuthtication'],
# 当认证为匿名用户时,request.user = '匿名用户'/None
'UNAUTHENTICATED_USER': lambda: '匿名用户', # None
# 当认证为匿名用户时,request.auth = None
'UNAUTHENTICATED_TOKEN': None,
# 权限配置
'DEFAULT_PERMISSION_CLASSES': ['api.utils.permission.MyPermission'],
# 节流配置
'DEFAULT_THROTTLE_CLASSES': [