기본적인 아이디어 (기본 장고 용어) :
등장 경우 django2.x에서 조절 (액세스 주파수 제어) 요구 사항을, 우리의 첫 번째 생각은 사용하는 것입니다 사전에 모든 저장 (DICT 유형) IP 주소, 기록 액세스 시간 에 특정 익명 사용자 (IP) 및 소개
{ 「111.222.3.44 」 : 1,000 , 900 , 700 , 500 , 10 ...] " 1.333.44.555 " [ 1200 , 900 , 20 , 10 .....] }
원래 요청 메시지 본문, 클라이언트의 REMOTE_ADDR IP 주소에서 저장된 싸다
에서 django.utils.deprecation의 수입 MiddlewareMixin 에서 django.http.response 수입 HttpResponse에의 수입 시간 MAX_PER_VISITED_NUMS = 3 VISITED_IP_THROTTLE = 딕셔너리 () 클래스 ThrottleMiddleware (MiddlewareMixin) : "" " 스로틀 미들웨어 분당 방문 VISITED_IP_THROTTLE 최대 수 "" " DEF는 (자체, 요청) request_allowed : " "" 액세스 제한 익명 사용자의 주파수를 제한하는 사용자 액세스 빈도의 제한을 "" " IP = request.META [ ' REMOTE_ADDR ' ] CUR_TIME는 = 로 time.time () 중 # 경우 리미터에 기록 IP IF IP 에 VISITED_IP_THROTTLE : visiting_record = VISITED_IP_THROTTLE [IP] 그동안은 visiting_record : # 마지막 방문리스트 간의 시간 차이보다 60 초 마지막 레코드 삭제를 기록 루프 계속 IF CUR_TIME - 60> = visiting_record [-1 ] visiting_record.pop ( -1 ) 계속 # 액세스 레코드 목록 액세스의 최대 수를 초과 IF LEN (visiting_record)> = MAX_PER_VISITED_NUMS : 반환 거짓 #을 마지막 액세스 시간 기록 목록에 60 초 미만의 visiting_record.insert (0, CUR_TIME) 반환 사실을 # 아니오 IP 액세스에 새로운 기록을 기록하지 VISITED_IP_THROTTLE [IP] = () 목록 VISITED_IP_THROTTLE [IP]를 취소하려면 (0 cur_time) 반환 사실을 데프 process_request (자체 요청) : 경우 : self.request_allowed (요청) 인쇄 (참) 반환 (HttpResponse에를 " 진정한 " ) 다른 : 인쇄 (false)를 반환 HttpResponse에를 ( " 거짓 " )
결과 :
이것은 액세스위한 적은 사용자 전역 변수 만 레코드 메모리 액세스, 실제 상황, 그것을 이용하는 것이 바람직하다 경우에 사용되는 레디 스를 캐싱하고 사용 해시 레코드를 저장하는 타입.
restframework 인증 :
사용자 정의 스로틀 제어
사용 레디 스 캐시 액세스 레코드 (해시 타입)
redispool.py은 (연결 풀링에 대한 자신의 레디 스에 대한 연결 정보의 매개 변수를 설정)
수입 레디 스 에서 vue_shop의 가져 오기 설정 REDIS_POOL = redis.ConnectionPool (** settings.REDIS_KWARGS)
throttle.py
수입 시간 수입 레디 스 에서 utils.redispool의 수입 REDIS_POOL의 수입 JSON 에서 rest_framework.throttling 수입 SimpleRateThrottle 클래스 AnonymityUserThrottle (객체) : "" " 사용자 정의 스로틀 익명 사용자, 캐시 액세스를 기록 레디 스를 사용하여 MAX_PER_VISITED_NUMS : 분 당 가장 높은 액세스 이름 : 해시 유형 이름에 캐싱 (레디 스) "" " MAX_PER_VISITED_NUMS = 3 이름 = " AnonymityVisitedRecord " 데프 allow_request (자기, 요청,보기) : "" " 로직에 액세스 여부를 결정 : PARAM 요청 : DRF의 요청 : PARAM보기 : : 리턴 : 부울 "" " IP_ADDR = request.META.get ( " REMOTE_ADDR " , 없음) cur_visit_time = 로 time.time () redis_conn = redis.Redis (connection_pool = REDIS_POOL) ips_record = redis_conn.hget (self.name, IP_ADDR) 인쇄 (ips_record) 경우 ips_record : history_visit_list = json.loads (ips_record.decode는 ()) 그동안 history_visit_list : # [120, 99, 40] #의 시간차 B 긴 액세스 시간과 현재 시간보다 60 초 이상을 A, B가 삭제하므로 사이클 IF cur_visit_time - history_visit_list [-1]> = 60 : history_visit_list.pop ( -1 ) redis_conn.hset (self.name, IP_ADDR, json.dumps (history_visit_list)) 계속 경우 렌 (history_visit_list)> self.MAX_PER_VISITED_NUMS을 : 반환 거짓 history_visit_list.insert (0 cur_visit_time) redis_conn.hset (self.name, IP_ADDR, json.dumps (history_visit_list)) 반환 사실을 new_ip_record = 리스트 () new_ip_record.insert (0 cur_visit_time) redis_conn.hset (self.name, IP_ADDR, json.dumps (new_ip_record)) 반환 사실을 데프 (자동) 기다립니다 "" " 선택적으로, 전에 대기하는 시간 (초)의 권장 수를 반환 다음 요청. "" " 반환 없음
결과 :
내장 스로틀 제어
class SimpleAnonymityUsertThrottle(SimpleRateThrottle): """ 使用restframework内置的节流类,针对于的匿名用户的访问控制 """ scope = "Anonymity" def get_cache_key(self, request, view): """ 返回用户的唯一标识 """ # return request.META.get("REMOTE_ADDR") return self.get_ident(request) class CertifiedUserThrottle(SimpleRateThrottle): """ 对认证通过的用户进行节流控制 """ scope = "CertifiedUser" def get_cache_key(self, request, view): """返回唯一用户标识""" return request.user.username
scope参数依赖配置:
REST_FRAMEWORK = { 'DEFAULT_THROTTLE_RATES': { 'Anonymity': '3/m', 'realUser': '6/m', }, }