抛出问题
对访问的频率进行控制(当然只是在一定程度上限制,若客服端换IP,疯狂注册账号没治)
通过获取用户的IP,实现一分钟内,只能访问三次。实际生产中应该记录放在数据库,或者放在缓存,或者放在文件中等等,我把记录直接放在这里,占用内存不说,还有就是服务端从启系统的话,记录全丢失。
视图路由与认证权限相同。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 from rest_framework.throttling import BaseThrottle 5 from rest_framework.throttling import SimpleRateThrottle 6 import time 7 8 VIST_RECORD = {} 9 10 11 class VisitThrottle(BaseThrottle): 12 13 def __init__(self): 14 self.history = None 15 16 def allow_request(self, request, view): 17 18 """ 19 一分钟访问三次最多 20 判断是否可以继续访问,频率是否达到最大 21 :param request: 22 :param view: 23 :return: True 可以继续访问 False表示访问频率太高要被限制 24 1.获取用户IP 25 """ 26 remote_addr = request.META.get('REMOTE_ADDR') 27 ctime = time.time() 28 if remote_addr not in VIST_RECORD: 29 VIST_RECORD[remote_addr] = [ctime,] 30 return True 31 history = VIST_RECORD.get(remote_addr) 32 self.history = history 33 while history and history[-1] < ctime - 60: 34 history.pop() 35 36 if len(history) < 3: 37 history.insert(0, ctime) 38 return True 39 40 def wait(self): 41 """ 42 还需要等多久才能被访问 43 :return: 44 """ 45 ctime = time.time() 46 return 60 - (ctime - self.history[-1])
当然内置的页帮我们写了这些环节,直接获取过来用即可
1 class VisitThrottle(SimpleRateThrottle): 2 scope = "Baidu" 3 4 def get_cache_key(self, request, view): 5 return self.get_ident(request) 6 7 8 class UserThrottle(SimpleRateThrottle): 9 """ 10 根据当前登录用户的访问次数限制 11 """ 12 scope = "BaiduUser" 13 14 def get_cache_key(self, request, view): 15 return request.user.username
全局配置:
1 REST_FRAMEWORK = { 2 # 认证 3 'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.auth.Authticate', ], 4 # 'DEFAULT_AUTHENTICATION_CLASSES': [], # AnonymousUser None配置文件中有 5 # 'UNAUTHENTICATED_USER': lambda: '匿名用户', 6 # 'UNAUTHENTICATED_USER': None, 7 # 'UNAUTHENTICATED_TOKEN': None, 8 # 权限 9 'DEFAULT_PERMISSION_CLASSES': ['api.utils.permission.Mypermission'], 10 # 节流 访问频率控制 11 "DEFAULT_THROTTLE_CLASSES": ['api.utils.throttle.VisitThrottle', ], 12 "DEFAULT_THROTTLE_RATES": { 13 "Baidu": '3/m', 14 "BaiduUser": '10/m', 15 } 16 17 }
局部配置:
1 throttle_classes = [VisitThrottle, ]
总结:自己定义节流类,在类中实现allow_request(都是这样子若没写前面几个组件都是抛错,看基类),wait两方法,当然wait可以不用写,当然看需求吧!
源码流程分析
APIView的dispatch---->封装request----->initial----->self.check_throttles(request)----->allow_request(request, self)(两种情况:True访问频率未达到最高次数,Flase访问频率已经达到最大的次数)
内置节流类
BaseThrottle allow_request主逻辑 get_ident获取IP wait超过次数需要多久恢复
SimpleRateThrottle 适用 跟我上面实现思路差不多 在settings中配置scope即可快捷
AnonRateThrottle 针对匿名用户的 配置scope = 'anon'
UserRateThrottle scope = 'user'
ScopedRateThrottle scope_attr = 'throttle_scope'