Django Rest Framework --用戶訪問頻率限制

自定義訪問頻率控制類結構

views.pyhtml

from rest_framework.throttling import BaseThrottle
import time
# 節流
visit_dict={}

class Visitthrottle(BaseThrottle):
    #經過IP作惟一標識符
    #問題:非登錄用戶一分鐘內只容許訪問3次
    def __init__(self):
        self.history=None

    def allow_request(self,request, view):
        #獲取IP地址
        remote_addr = self.get_ident(request)
        ctime=time.time()
        if remote_addr not in visit_dict:
            visit_dict[remote_addr]=[ctime,]
            return True
        self.history = visit_dict.get(remote_addr)
        while self.history and self.history[-1] <ctime - 60:
            self.history.pop()
        if len(self.history)<3:
            self.history.insert(0,ctime)
            return True

    def wait(self):
        ctime=time.time()
        return 60-(ctime-self.history[-1])
class TestThrottle(APIView):
    throttle_classes = [VisitThrottle,]
     
    def get(self, request, *args, **kwargs):
        pass
        '''
        等等一系列的視圖功能方法
        '''

實現原理分析:python

  • 須要使用用戶IP地址做爲惟一標識符,若是使用用戶登錄帳號做爲惟一標識符,一個用戶可能擁有多個帳號,則達不到節流的目的,但使用IP地址也不是說必定不能改變,但相比於登錄帳號,使用IP地址更能達到節流的做用。
  •  以IP地址做爲KEY鍵,多個訪問時間形參列表做爲value存入字典中,用戶每次訪問讀取字典,判斷最後一次訪問時間與此次訪問時間相差時間,相差時間大於60秒,刪除時間列表中最後元素,而後判斷列表長度是否小於3,若是小於3,表示一分鐘內未訪問3次,容許繼續訪問。
  • 若是不容許訪問,會執行wait函數,返回須要等待時間。
  • 可是在項目開發中不使用自定義節流類,是由於drf中已經實現了節流方法。內置接口代碼基本結構,內置節流類的實現原理與自定義節流類原理相同。

內置節流類結構

settings.py:django

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES':['api.utils.mythrottle.UserThrottle',]
    'DEFAULT_THROTTLE_RATES': {
        '未認證用戶': '10/m',
        '已認證用戶': '100/h',
    },
}

mythrottle.py:api

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import exceptions
from rest_framework.throttling import SimpleRateThrottle
 
 
class VisitThrottle(SimpleRateThrottle):
    scope = "未認證用戶"
 
    def get_cache_key(self, request, view):
        return  self.get_ident(request)
       
 
class UserThrottle(SimpleRateThrottle):
    scope = "已認證用戶"
 
    def get_cache_key(self, request, view):
        return  request.user  # 認證經過後,認證方法authenticate的返回值之一<br><br>


class TestThrottle(APIView):<br>  # 這樣設置後,節流功能就會使用VisitThrottle類,而不會使用UserThrottle類
    throttle_classes = [VisitThrottle,]
     
    def get(self, request, *args, **kwargs):
        pass
        '''
        等等一系列的視圖功能方法
        '''

  這裏使用的節流類是繼承了SimplePateThrottle類,而這個類利用了django內置的緩存來存儲訪問記錄。經過全局節流設置,全部的視圖類默認是使用UserThrottle類進行節流,若是不想使用默認的類就自定義給throttle_classes屬性變量賦值,如:「throttle_classes = [VisitThrottle,]」。看到內置節流類的使用,可能一臉懵逼,下面進行源碼分析。緩存

源碼分析

與以前認證權限控制的源碼分析方法一致,先進入函數入口dispatch方法,封裝完新的request對象後,進入initialize_request方法,咱們會發現還有一個函數調用咱們沒有分析,因此這就是咱們的節流函數。ide

1.爲何會使用scope屬性變量,有什麼用?函數

進入check_throttles函數,是否以爲很熟悉?沒錯在get_throttles方法中確定也是一個列表生產式,返回一個有節流類實例組成的列表。源碼分析

  

 在列表生成式中,先對內置類SimplePateThrottle進行實例化,在實例化中去拿到scope的值,而且根據值做爲key值去配置文件中拿到對應value值。在parse_rate方法中能夠看出value是又‘/’分隔的一個字符串。spa

  

2.爲何會使用‘get_cache_key’方法,該方法的返回值是什麼?rest

實例化完成後,執行allow_request方法,首先執行的是get_cache_key’方法

 

在get_cache_key’方法中裏面什麼都沒寫,因此就是說咱們在使用內置節流類時,必須重構get_cacha_key方法,不然會拋出異常,由於內置節流類是經過django緩存實現,因此須要給它一個惟一標識符,在這裏我選擇的是選擇用戶的IP地址進行惟一確認,因此這裏的返回值爲一個惟一標識符。

 

接下來的操做與咱們自定義節流類的原理一致。最後若是返回false,調用wait方法,拋出異常

3.爲何使用‘throttle_classes’屬性變量,它有什麼用?

get_throttles方法返回的是一個列表生成式,而這裏的throttle_classes就是在視圖類TestThrottle中使用的,該變量就保存節流類對象。

 4.‘DEFAULT_THROTTLE_CLASSES’從那裏來,有什麼用?

經過throttle_classes屬性變量,跳轉到該圖,能夠看到配置文件中說的「DEFAULT_THROTTLE_CLASSES」,它是用來經過配置文件settings來對全局節流類進行配置,功能等價於throttle_classes屬性變量。

 5.‘DEFAULT_THROTTLE_RATES’從那裏來,有什麼用?

由SimpleRateThrottle類和上文對scope屬性變量的分析可知,DEFAULT_THROTTLE_RATES就是爲了存儲在配置文件中設置的不一樣的節流方法的。

 

綜上所述,能夠看出,在利用內置節流接口時,經過配置文件settings的設置和提供該接口所需的用戶惟一標識外,不須要咱們作再多的操做,這就造成了咱們上文寫的內置接口代碼基本結構的樣式。

相關文章
相關標籤/搜索