DRF之許可權和頻率限制

Yang`發表於2021-07-11

一、許可權

許可權可以限制使用者對檢視的訪問和對具體資料物件的訪問。

  • 在執行檢視的dispatch方法前,會先進行檢視訪問許可權的判斷
  • 在通過get_object獲取物件時,會進行模型物件訪問許可權的判斷

原始碼分析

核心原始碼——>APIView——>dispatch——>initial——>self.check_permissions(request)

def check_permissions(self, request):
    
    # 遍歷許可權物件列表得到一個個許可權物件(許可權器),進行許可權認證
    for permission in self.get_permissions():
        
        # 許可權類一定要有一個has_permission許可權方法,用來做許可權認證的
        # 引數:許可權物件self、請求物件request、檢視類物件view
        """
           has_permission(self, request, view):
        """
        # 返回值:有許可權返回True、無許可權返回False
        if not permission.has_permission(request, self):
            self.permission_denied(
                request,
                message=getattr(permission, 'message', None),
                code=getattr(permission, 'code', None)
            )

許可權使用

寫一個類,繼承BasePermission,重寫has_permission,如果許可權通過,就返回True,不通過就返回False。

from rest_framework.permissions import BasePermission


class UserPermission(BasePermission):
    def has_permission(self, request, view):
        # 由於已經認證過了,request內就已經有了user物件了,當前使用者

        user = request.user     # 當前登入使用者
        # 如果該欄位用了choice,那麼可以使用get_欄位名_display(),取出choice後面的中文
        print(user.get_user_type_display())

        if user.user_type == 1:     # 不是超級使用者不能訪問
            return True
        else:
            return False

如何使用:

# 區域性使用
from app01.app01_auth import UserPermission

class TestView(APIView):
    authentication_classes = [TokenAuthentication]		# 認證配置
    permission_classes = [UserPermission]				# 許可權配置
    
    
# 全域性使用
REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":[
        "app01.app01_auth.TokenAuthentication",		# 全域性認證配置
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'app01.app01_auth.UserPermission',			# 全域性許可權配置
    ],
}

# 區域性禁用 settings.py
class TestView(APIView):
    permission_classes = []				# 區域性禁用許可權配置

內建許可權

內建許可權類

from rest_framework.permissions import AllowAny,IsAuthenticated,IsAdminUser,IsAuthenticatedOrReadOnly

- AllowAny 				允許所有使用者
- IsAuthenticated 		僅通過認證的使用者
- IsAdminUser 			僅管理員使用者
- IsAuthenticatedOrReadOnly 已經登陸認證的使用者可以對資料進行增刪改操作,沒有登陸認證的只能檢視資料。

如何使用

# 1 建立超級管理員	>>python manage.py createsuperuser

from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication
class TestView(APIView):
    authentication_classes=[SessionAuthentication,]
    permission_classes = [IsAdminUser]
    def get(self,request,*args,**kwargs):
        return Response('這是測試資料,超級管理員可以看')
# 3 超級使用者登入到admin,再訪問test就有許可權
# 4 正常的話,普通管理員,沒有許可權看(判斷的是is_staff欄位)

二、頻率

可以用來減輕伺服器壓力,對介面訪問的頻率進行限制

內建頻率限制

由於大部分需求使用內建的頻率限制就已經可以了,所以主要看看內建的頻率限制

限制未登入使用者:AnonRateThrottle

也就是限制所有匿名未認證使用者,使用IP區分使用者。anon設定頻次

# 全域性使用 settings.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',	
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '5/m',		# 每分鐘訪問次數
    }
}

# views.py
from rest_framework.views import APIView

class TestView(APIView):

    def get(self, request):
        return Response('我是未登入使用者,每分鐘只能訪問5次')
    
# -------------------------------------------------------------------

# 區域性使用
# 還是需要先在settings.py中配置訪問次數
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'anon': '5/m',
    }
}

# views.py
from rest_framework.throttling import AnonRateThrottle
from rest_framework.views import APIView

class TestView(APIView):
    throttle_classes = [AnonRateThrottle]	# 區域性使用

    def get(self, request):
        return Response('我是未登入使用者,每分鐘只能訪問5次')

限制登入使用者:UserRateThrottle

需求:未登入使用者1分鐘訪問5次,登入使用者一分鐘訪問10次

對認證使用者限制,使用User id 來區分,user 設定頻次

但是這個有侷限性,它只能是auth_user表,admin這套系統才能使用

# 全域性使用 settings.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',	# 未登入使用者
        'rest_framework.throttling.UserRateThrottle'	# 登入使用者
    ),
    'DEFAULT_THROTTLE_RATES': {
        'user': '10/m',		# 登入使用者頻率
        'anon': '5/m',		# 未登入使用者頻率
    }
}

from rest_framework.views import APIView

class TestView(APIView):

    def get(self, request):
        return Response('未登入使用者5次,登入之後10次')

IP頻率限制:SimpledRateThrottle

限制使用者對於每個檢視的訪問頻率,使用IP限制

# 1、寫一個類,繼承SimpleRateThrottle,重寫 get_cache_key
# app01_auth.py
from rest_framework.throttling import SimpleRateThrottle

class App01_Throttle(SimpleRateThrottle):
    scope = 'luffy'

    def get_cache_key(self, request, view):
        # 返回什麼原始碼中的key就是什麼
        return request.META.get('REMOTE_ADDR')
    
    
    
# 2、全域性配置頻率次數	settings.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'luffy': '5/m'      # key要根據類中的scope對應
    },
}



# 3、區域性使用	views.py
from rest_framework.views import APIView
from app01.app01_auth import App01_Throttle


class TestView(APIView):
    throttle_classes = [App01_Throttle]		# 區域性使用配置

    def get(self, request):
        return Response('IP限制每分鐘訪問5次')
    
# 全域性使用需要在settings.py配置
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'app01.app01_auth.App01_Throttle',	# 全域性及配置
    ),
    'DEFAULT_THROTTLE_RATES': {
        'luffy': '5/m'      # key要根據類中的scope對應
    },
}

相關文章