This is the 16th day of my participation in Gwen Challenge

Anonymous users control the access frequency by IP address. Logged-in users control the access frequency by token

1 Implementation Principle

Put all login record time in a list, when users request pages, use the time minus the constraints of time interval, and then exclude is less than the time record, then calculate the time gap on the number of records, if the article number less than the provisions of article can access and the current time added to the list, if is greater than or equal to does not let its access.

2 process

2.1 DRF source code

  1. When a user requests a web page, the background allows as_views() in the URL of the interface, runs the as_view method, and enters the dispatch method of the APIView class
  2. Enter the self.check_throttles(request) method in the self.initial method
  3. Loop through the allow_request method in the throttling class

2.2 Custom methods

  1. Return True if accessible, False if not, and then check_throttles. If False, run the wait method in the SimpleRateThrottle class to get the time to wait displayed on the page

3 the return value

  • True, access is allowed
  • Return value of wait() : Returns an integer indicating how long it will be until the next access is available

4 use

Override the native method basethrottle.allow_request

utils/throttle.py

from rest_framework.throttling import BaseThrottle
import time

Define global variables to store access records
VISIT_RECORD = {}

# need to inherit BaseThrottle
class VisitThrottle(BaseThrottle) :
    You can only access 3 times in 60 seconds.

    def __init__(self) : # count the remaining access time with await
        self.history = []

    # override the allow_request method in the defined class, returning True or False to indicate access or too frequent access
    def allow_request(self, request, view) :
        # 1. Obtain the user IP
        # Method 1: Obtain user IP through native method
        # remote_addr = request.META.get('REMOTE_ADDR')

        Method 2: Obtain the user's unique IP address from the parent method
        remote_addr = self.get_ident(request)
        ctime = time.time()
        # this is the user's first access, log it, and return True to allow continued access
        if remote_addr not in VISIT_RECORD:
            print("There is no such IP")
            VISIT_RECORD[remote_addr] = [ctime,]
            return True
        If it is not the first time, get all records
        history = VISIT_RECORD.get(remote_addr)
        self.history = history

        # Judge whether the difference between the initial moment and the present moment is within the specified time range, such as within 60s. If not,
        Can remove the initial time record
        while history and history[-1] < ctime - 60:
            # Delete the last one
            history.pop()
        All the time records in the list are within the specified time range. The number of time is judged as the number of access times
        if len(history) < 3:
            history.insert(0, ctime)
            return True
        
    # How many seconds do I have to wait for access
    def wait(self) :
        ctime = time.time()
        return 8-(ctime-self.history[-1])
Copy the code

5 introduced

5.1 the global

# settings.py
'DEFAULT_THROTTLE_CLASSES': ['apps.api.utils.throttle.VisitThrottle'].Copy the code

5.2 local

class AuthView(APIView) :
    "" for user login authentication ""
    throttle_classes = [VisitThrottle,]
Copy the code

5.3 Inheriting built-in Classes

utils/throttle.py

from rest_framework.throttling import  SimpleRateThrottle

# Restrictions on tourists
class VisitThrottle(SimpleRateThrottle) :
    scope = "Vistor"
    def get_cache_key(self, request, view) :
        The only representation is IP
        return self.get_ident(request)
    
# Restrictions on login users
class UserThrottle(SimpleRateThrottle) :
    scope = "User"
    def get_cache_key(self, request, view) :
        The only representation is the user name
        return self.user.username
Copy the code

Scope looks for the Key of DEFAULT_THROTTLE_RATES dictionary from settings.py, which is the access frequency limit. Scope can distinguish the different limits of different functions. Get_cache_key (self, request, view) returns a unique identifier to distinguish between different users. For anonymous users, the IP is returned to the cache to restrict access, and for registered users, the username (unique) is used to distinguish between different users.

The global application

REST_FRAMEWORK = {
    ...
    'DEFAULT_THROTTLE_RATES': {
        The limit for visitors is 3 times per minute
        'Vistor': '3/m'.Limit logins to 10 times per minute
        'User': '10/m'}}Copy the code