DRF之訪問權限控制和訪問頻率控制(節流)


權限控制

前言

用戶驗證用戶權限,根據不同訪問權限控制對不同內容的訪問。

建議了解視圖、token驗證的內容。

使用流程

  1. 自定義訪問權限類,繼承BasePermission,重寫has_permission()方法,如果權限通過,就返回True,不通過就返回Falsehas_permission()方法接受兩個參數,分別是requestview,也就是視圖類的實例化本身。

image-20210106113656701

  1. 配置。

局部配置:

permission_classes = [MyUserPermission]

全局配置:

REST_FRAMEWORK={
    'DEFAULT_PERMISSION_CLASSES': ['libs.MyAuth.UserPermission',],
}

示例

class SVIPPermission(BasePermission):   # 推薦繼承BasePermission類
    # message = 'You do not have permission to perform this action.'#默認值
    message = '無此權限!!!'

    def has_permission(self, request, view):
        if request.user.user_type == 3:
            return False    # False為沒權限
        # view.queryset =   # 可以使用這種方式控制視圖中要處理的數據(根據不同權限)
        return True         # True為有權限

源碼分析

進入dispatch函數,查看initial方法(執行三大驗證)中的check_permissions方法:

image-20201230163053258

self.check_permissions(request)將會根據request中的用戶內容進行權限控制。

image-20201230163450342

image-20201230163538055

image-20210106113841241

由上可知,permission_classes要么讀取配置文件中的DEFAULT_PERMISSION_CLASSES(全局),要么就在視圖類中直接對permission_classes賦值(局部)。

節流限制

前言

控制網站訪問頻率。

使用流程

  1. 自定義限制類,繼承BaseThrottle
  2. 指定從配置文件中要讀取的scope(key),形式為scope="key"

全局配置:

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/day',
        'user': '1000/day'
    }
}

局部配置:

throttle_classes = [UserRateThrottle]

就比如UserRateThrottle,繼承了SimpleRateThrottle,指定了它所限制的scope,重寫了get_cache_key方法。

image-20210106115349546

源碼分析

APIViewinitial方法中,三大驗證還剩下最后一個沒有分析,那就是訪問頻率驗證,如下圖:

image-20210106115306589

接下來讓我們查看check_throttles,可以看到,驗證訪問頻率的時候,調用的方法為頻率驗證類的allow_request方法。

image-20210106122326700

其中get_throttles用的還是老套路:

image-20210106122353228

示例

自定義一個頻率限制類:

from rest_framework.throttling import BaseThrottle
import time
 
# 存放訪問記錄(一般放數據庫或者緩存中)
VISIT_RECORD = {}
 
class VisitThrottle(BaseThrottle):
 
    def __init__(self):
        self.history = None
 
    def allow_request(self, request, view):
        # 1. 獲取用戶ip
        remote_addr = request.META.get("REMOTE_ADDR")

        # 2. 添加到訪問記錄中
        ctime = time.time()
        
        # 當VISIT_RECORD中沒有這個記錄,可以直接訪問,添加一個記錄
        if remote_addr not in VISIT_RECORD:
            VISIT_RECORD[remote_addr] = [ctime, ]
            return True
        
        history = VISIT_RECORD.get(remote_addr)
        self.history = history
        
        # 拿到最后歷史記錄里面的最后一個時間,如果最后一個時間小於當前時間-60(一分鍾之前的記錄)
        while history and history[-1] < ctime - 60:
            history.pop()
        
        if len(history) < 3:	# 允許
            history.insert(0, ctime)
            return True
 
        return False  # False表示訪問頻率太高被限制
 
    def wait(self):
        """
        還需要等多少秒可以訪問
        :return:
        """
        ctime = time.time()
        return 60 - (ctime - self.history[-1])

注意:官方內置的 SimpleRateThrottle 類中對scope的處理值得一看。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM