1. 程式人生 > >DRF之訪問許可權控制和訪問頻率控制(節流)

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

# 許可權控制 ## 前言 **使用者驗證使用者許可權,根據不同訪問許可權控制對不同內容的訪問。** 建議瞭解檢視、token驗證的內容。 ## 使用流程 1. 自定義訪問許可權類,繼承`BasePermission`,重寫`has_permission()`方法,如果許可權通過,就返回`True`,不通過就返回`False`。`has_permission()`方法接受兩個引數,分別是`request`和`view`,也就是檢視類的例項化本身。 ![image-20210106113656701](https://img2020.cnblogs.com/blog/2056368/202101/2056368-20210106113657150-1816818317.png) 2. 配置。 區域性配置: ```python permission_classes = [MyUserPermission] ``` 全域性配置: ```python REST_FRAMEWORK={ 'DEFAULT_PERMISSION_CLASSES': ['libs.MyAuth.UserPermission',], } ``` ## 示例 ```python 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](https://img2020.cnblogs.com/blog/2056368/202012/2056368-20201230163053884-1093386257.png) `self.check_permissions(request)`將會根據`request`中的使用者內容進行許可權控制。 ![image-20201230163450342](https://img2020.cnblogs.com/blog/2056368/202012/2056368-20201230163450875-1494222285.png) ![image-20201230163538055](https://img2020.cnblogs.com/blog/2056368/202012/2056368-20201230163538522-8789747.png) ![image-20210106113841241](https://img2020.cnblogs.com/blog/2056368/202101/2056368-20210106113841738-889803283.png) 由上可知,`permission_classes`要麼讀取配置檔案中的`DEFAULT_PERMISSION_CLASSES`(全域性),要麼就在檢視類中直接對`permission_classes`賦值(區域性)。 # 節流限制 ## 前言 **控制網站訪問頻率。** ## 使用流程 1. 自定義限制類,繼承`BaseThrottle`。 2. 指定從配置檔案中要讀取的scope(key),形式為`scope="key"` 全域性配置: ```python REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle' ], 'DEFAULT_THROTTLE_RATES': { 'anon': '100/day', 'user': '1000/day' } } ``` 區域性配置: ```python throttle_classes = [UserRateThrottle] ``` 就比如`UserRateThrottle`,繼承了`SimpleRateThrottle`,指定了它所限制的`scope`,重寫了`get_cache_key`方法。 ![image-20210106115349546](https://img2020.cnblogs.com/blog/2056368/202101/2056368-20210106115349989-1102939528.png) ## 原始碼分析 在`APIView`的`initial`方法中,三大驗證還剩下最後一個沒有分析,那就是訪問頻率驗證,如下圖: ![image-20210106115306589](https://img2020.cnblogs.com/blog/2056368/202101/2056368-20210106115307148-1750509663.png) 接下來讓我們檢視`check_throttles`,可以看到,驗證訪問頻率的時候,呼叫的方法為頻率驗證類的`allow_request`方法。 ![image-20210106122326700](https://img2020.cnblogs.com/blog/2056368/202101/2056368-20210106122327226-603589863.png) 其中`get_throttles`用的還是老套路: ![image-20210106122353228](https://img2020.cnblogs.com/blog/2056368/202101/2056368-20210106122353718-1605526304.png) ## 示例 自定義一個頻率限制類: ```python 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`的處理值得