目錄django
與身份驗證和限制一塊兒,權限肯定是應該授予仍是拒絕訪問請求。api
在容許任何其餘代碼繼續以前,權限檢查始終在視圖的最開始運行。權限檢查一般使用 request.user
和 request.auth
屬性中的身份驗證信息來肯定是否應容許傳入請求。app
權限用於授予或拒毫不同類別的用戶訪問API的不一樣部分。框架
最簡單的權限類型是容許訪問任何通過身份驗證的用戶,並拒絕訪問任何未經身份驗證的用戶。這對應IsAuthenticated
於REST框架中的類。ide
稍微不那麼嚴格的權限樣式是容許對通過身份驗證的用戶進行徹底訪問,但容許對未經身份驗證的用戶進行只讀訪問。這對應IsAuthenticatedOrReadOnly
於REST框架中的類。rest
可使用該DEFAULT_PERMISSION_CLASSES
設置全局設置默認權限策略。例如:code
REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
若是未指定,則此設置默認容許不受限制的訪問:orm
'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.AllowAny', )
您還可使用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)
或者,使用@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)
若是它們繼承自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", } }