DRF 權限 頻率

DRF 權限 頻率

  • 什麼是權限
    • 簡單的說就是對某件事情決策的範圍和程度,例如對數據的操做,普通用戶只能查看,管理員用戶能夠增刪改查

權限組件源碼

執行APIView的方法,APIView返回View中的view函數,而後調用的dispatch方法,而後執行initial方法python

img

點擊check_permissions服務器

img

必定要有has_permission方法~不然就會拋出異常這也是框架給我提供的鉤子~~數據結構

咱們先看到在rest_framework.permissions這個文件中~存放了框架給咱們提供的全部權限的方法框架

img

權限的詳細用法

  • initial方法初始化這些組件的時候也是有順序的ide

  • 版本在前面~而後是認證,而後是權限~ 最後是頻率函數

  • 因此你們要清楚咱們的權限執行的時候~咱們的認證已經執行結束了spa

    前提在model中的UserInfo表中加了一個字段~用戶類型的字段作好數據遷移~~3d

1.定義一個權限類

class MyPermission(BasePermission):
    message = "VIP用戶才能訪問"

    def has_permission(self, request, view):
        """
        自定義權限只有vip用戶能訪問,
        注意咱們初始化時候的順序是認證在權限前面的,因此只要認證經過~
        咱們這裏就能夠經過request.user,拿到咱們用戶信息
        request.auth就能拿到用戶對象
        """
        if request.user and request.auth.type == 2:
            return True
        else:
            return False

2 局部註冊

class TestAuthView(APIView):
    # 執行認證
    authentication_classes = [MyAuth, ]
    # 執行權限
    permission_classes = [MyPermission, ]

    def get(self, request, *args, **kwargs):
        print(request.user)
        print(request.auth)
        username = request.user
        return Response(username)

2.1 全局註冊

REST_FRAMEWORK = {
    # 默認使用的版本控制類
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
    # 容許的版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],
    # 版本使用的參數名稱
    'VERSION_PARAM': 'version',
    # 默認使用的版本
    'DEFAULT_VERSION': 'v1',
    # 配置全局認證
    # 'DEFAULT_AUTHENTICATION_CLASSES': ["BRQP.utils.MyAuth", ]
    # 配置全局權限
    "DEFAULT_PERMISSION_CLASSES": ["BROP.utils.MyPermission"]

DRF的頻率

  • 頻率限制的做用版本控制

    • 開放平臺的API接口調用須要限制其頻率,以節約服務器資源和避免惡意的頻繁調用。
  • 頻率的源碼流程和版本,認證,權限都是同樣的rest

  • 原理

    • DRF中的頻率控制基本原理是基於訪問次數和時間的,固然咱們能夠經過本身定義的方法來實現。

      當咱們請求進來,走到咱們頻率組件的時候,DRF內部會有一個字典來記錄訪問者的IP,

      以這個訪問者的IP爲key,value爲一個列表,存放訪問者每次訪問的時間,

      { IP1: [第三次訪問時間,第二次訪問時間,第一次訪問時間],}

      把每次訪問最新時間放入列表的最前面,記錄這樣一個數據結構後,經過什麼方式限流呢~~

      若是咱們設置的是10秒內只能訪問5次,

        -- 1,判斷訪問者的IP是否在這個請求IP的字典裏

        -- 2,保證這個列表裏都是最近10秒內的訪問的時間

            判斷當前請求時間和列表裏最先的(也就是最後的)請求時間的查

            若是差大於10秒,說明請求以及不是最近10秒內的,刪除掉

            繼續判斷倒數第二個,直到差值小於10秒

        -- 3,判斷列表的長度(即訪問次數),是否大於咱們設置的5次,

            若是大於就限流,不然放行,並把時間放入列表的最前面。

頻率的詳細用法

1.自定義的方法

  • 自定義的頻率限制類

    VISIT_RECORD = {}
    class MyThrottle(object):
    
        def __init__(self):
            self.history = None
    
        def allow_request(self, request, view):
            """
            自定義頻率限制60秒內只能訪問三次
            """
            # 獲取用戶IP
            ip = request.META.get("REMOTE_ADDR")
            timestamp = time.time()
            if ip not in VISIT_RECORD:
                VISIT_RECORD[ip] = [timestamp, ]
                return True
            history = VISIT_RECORD[ip]
            self.history = history
            history.insert(0, timestamp)
            while history and history[-1] < timestamp - 60:
                history.pop()
            if len(history) > 3:
                return False
            else:
                return True
    
        def wait(self):
            """
            限制時間還剩多少
            """
            timestamp = time.time()
            return 60 - (timestamp - self.history[-1])
  • 配置自定義的頻率限制

    REST_FRAMEWORK = {
        # ......
        # 頻率限制的配置
        "DEFAULT_THROTTLE_CLASSES": ["Throttle.throttle.MyThrottle"],
        }
    }

2. 使用自帶的頻率限制類

  • 在settings.py中配置頻率限制

    REST_FRAMEWORK = {
        # 頻率限制的配置
        # "DEFAULT_THROTTLE_CLASSES": ["Throttle.throttle.MyVisitThrottle"],
        "DEFAULT_THROTTLE_CLASSES": ["Throttle.throttle.MyThrottle"],
        "DEFAULT_THROTTLE_RATES":{
            'WD':'5/m',         #速率配置每分鐘不能超過5次訪問,WD是scope定義的值,
    
        }
    }
  • 定義

from rest_framework.throttling import SimpleRateThrottle


class MyVisitThrottle(SimpleRateThrottle):
    scope = "WD"

    def get_cache_key(self, request, view):
        return self.get_ident(request)
  • 使用

    class TestView(APIView):
        throttle_classes = [MyVisitThrottle, ]
    
        def get(self, request, *args, **kwargs):
            # self.dispatch
            print(request.user)
            print(request.auth)
            return Response('GET請求,響應內容')
相關文章
相關標籤/搜索