Django REST framework - 權限和限制

Django REST framework 權限和限制

(你能幹什麼)

與身份驗證和限制一塊兒,權限肯定是應該授予仍是拒絕訪問請求。api

在容許任何其餘代碼繼續以前,權限檢查始終在視圖的最開始運行。權限檢查一般使用 request.userrequest.auth 屬性中的身份驗證信息來肯定是否應容許傳入請求。app

權限用於授予或拒毫不同類別的用戶訪問API的不一樣部分。框架

最簡單的權限類型是容許訪問任何通過身份驗證的用戶,並拒絕訪問任何未經身份驗證的用戶。這對應IsAuthenticated於REST框架中的類。ide

稍微不那麼嚴格的權限樣式是容許對通過身份驗證的用戶進行徹底訪問,但容許對未經身份驗證的用戶進行只讀訪問。這對應IsAuthenticatedOrReadOnly於REST框架中的類。rest

設置權限的方法

  1. 可使用該DEFAULT_PERMISSION_CLASSES設置全局設置默認權限策略。例如:code

    REST_FRAMEWORK = {
         'DEFAULT_PERMISSION_CLASSES': (
                 'rest_framework.permissions.IsAuthenticated',
         )
     }

    若是未指定,則此設置默認容許不受限制的訪問:orm

    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
     )
  2. 您還可使用APIView基於類的視圖在每一個視圖或每一個視圖集的基礎上設置身份驗證策略。對象

    from rest_framework.permissions import IsAuthenticated
    from rest_framework.response import Response
    from rest_framework.views import APIView繼承

    class ExampleView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
         content = {
             'status': 'request was permitted'
         }
         return Response(content)
  3. 或者,使用@api_view具備基於功能的視圖的裝飾器。

    from rest_framework.decorators import api_view, permission_classes
     from rest_framework.permissions import IsAuthenticated
     from rest_framework.response import Response
    
     @api_view(['GET'])
     @permission_classes((IsAuthenticated, ))
     def example_view(request, format=None):
         content = {
             'status': 'request was permitted'
         }
         return Response(content)

注意 :當您經過類屬性或裝飾器設置新的權限類時,您告訴視圖忽略settings.py文件中的默認列表集。

若是它們繼承自rest_framework.permissions.BasePermission,則可使用標準Python按位運算符組合權限。例如,IsAuthenticatedOrReadOnly能夠寫成:

from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
from rest_framework.views import APIView

class ReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS

class ExampleView(APIView):
    permission_classes = (IsAuthenticated|ReadOnly,)

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

案例

此案例基於 Django REST framework 認證

第一步: 定義一個權限類

"""

本身動手寫一個權限組件
"""
from rest_framework.permissions import BasePermission

class MyPermission(BasePermission):

message = '只有VIP才能訪問'

def has_permission(self, request, view):
    # 認證類中返回了token_obj.user, request_token
    # request.auth 等價於request_token
    if not request.auth:
        return False
    # request.user爲當前用戶對象
    if request.user and request.user.type == 1:  # 若是是VIP用戶
        print("requ", request.user, type(request.user))
        return True
    else:
        return False

第二步: 使用

視圖級別

class CommentViewSet(ModelViewSet):

    queryset = models.Comment.objects.all()
    serializer_class = app01_serializers.CommentSerializer
    authentication_classes = [MyAuth, ]
    permission_classes = [MyPermission, ]

全局級別設置

# 在settings.py中設置rest framework相關配置項
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
    "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
}

---


限制

(你一分鐘能幹多少次?)**好像有點污~~ ###

第一步: 自定義限制類

import time

# from rest_framework.throttling import
visit_record = {}


class MyThrottle(object):

def __init__(self):
    self.history = None

def allow_request(self, request, view):
    # 拿到當前的請求的ip做爲訪問記錄的 key
    ip = request.META.get('REMOTE_ADDR')
    # 拿到當前請求的時間戳
    now = time.time()
    if ip not in visit_record:
        visit_record[ip] = []
    # 把當前請求的訪問記錄拿出來保存到一個變量中
    history = visit_record[ip]
    self.history = history
    # 循環訪問歷史,把超過10秒鐘的請求時間去掉
    while history and now - history[-1] > 10:
        history.pop()
    # 此時 history中只保存了最近10秒鐘的訪問記錄
    if len(history) >= 3:
        return False
    else:
        # 判斷以前有沒有訪問記錄(第一次來)
        self.history.insert(0, now)
        return True

def wait(self):
    """告訴客戶端還需等待多久"""
    now = time.time()
    return self.history[-1] + 10 - now


# history = ['9:56:12', '9:56:10', '9:56:09', '9:56:08']  # '9:56:18' - '9:56:12'

# history = ['9:56:19', '9:56:18', '9:56:17', '9:56:08']

# 最後一項到期的時間就是下一次容許請求的時間

# 最後一項到期的時間:now - history[-1] > 10

# 最後一項還剩多少時間過時
# history[-1] + 10 - now

第二步: 使用

視圖中使用

class CommentViewSet(ModelViewSet):

    queryset = models.Comment.objects.all()
    serializer_class = app01_serializers.CommentSerializer
    throttle_classes = [MyThrottle, ]

全局中使用

# 在settings.py中設置rest framework相關配置項
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
    "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
    "DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]
}

嫌麻煩的話,還可使用內置限制類,哈哈~

from rest_framework.throttling import SimpleRateThrottle


class VisitThrottle(SimpleRateThrottle):

    scope = "xxx"

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

全局配置

# 在settings.py中設置rest framework相關配置項
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
    # "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
    "DEFAULT_THROTTLE_CLASSES": ["app01.utils.VisitThrottle", ],
    "DEFAULT_THROTTLE_RATES": {
        "xxx": "5/m",
    }
}
相關文章
相關標籤/搜索