正常網站開發的情況下,使用者的身份驗證或識别本身出現問題是無法進行通路資訊或代碼。
基于 DFR 進行權限的設定可以設定身份認證和權限組合使用,用來确定請求是否傳回資料還是拒絕請求資料。
雖然身份驗證是檢查使用者身份的過程(請求來自的使用者所簽署的令牌),但授權是檢查請求使用者是否具有執行請求的必要權限的過程。
DRF 中的授權過程由權限覆寫。
Permissions 權限
權限檢視方法
check_permissions根據請求資料檢查是否應允許請求。
class APIView(View):
def check_permissions(self, request):
for permission in self.get_permissions():
if not permission.has_permission(request, self):
self.permission_denied(
request,
message=getattr(permission, 'message', None),
code=getattr(permission, 'code', None)
)
check_object_permissions根據請求和對象資料的組合檢查是否應允許請求。
class APIView(View):
def check_object_permissions(self, request, obj):
for permission in self.get_permissions():
if not permission.has_object_permission(request, self, obj):
self.permission_denied(
request,
message=getattr(permission, 'message', None),
code=getattr(permission, 'code', None)
)
check_permissions 在執行視圖處理程式之前調用,而check_object_permissions 不會執行。
class XXXXAPI(APIView):
def get(self, request, pk):
data= get_object_or_404(data.objects.all(), pk=pk)
self.check_object_permissions(request, data)
serializer = MessageSerializer(data)
return Response(serializer.data)
權限檢視
運作視圖前檢查每個請求的權限,如果檢查失敗則會引發 exceptions.PermissionDenied 異常并且不會運作視圖代碼。
- 401:請求未成功進行身份驗證。
- 403:請求已成功通過身份驗證,,但權限被拒絕禁止的響應。
def get_object(self):
obj = get_object_or_404(self.get_queryset(), pk=self.kwargs["pk"])
self.check_object_permissions(self.request, obj)
return obj
認證的基礎方式
- IsAuthenticated,允許已認證并通過認證的使用者情況可以進行後續操作。
- IsAdminUser,使用者身份中 user.is_staff 是 True 被允許。
- IsAuthenticatedOrReadOnly,允許已認證使用者讀取和修改,未認證使用者隻讀。
權限政策設定
settings.py 進行權限配置。
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',# IsAuthenticated 僅通過認證的使用者
'rest_framework.permissions.AllowAny', # AllowAny 允許所有使用者
'rest_framework.permissions.IsAdminUser',# IsAdminUser 僅管理者使用者
'rest_framework.permissions.IsAuthenticatedOrReadOnly', # IsAuthenticatedOrReadOnly 認證的使用者可以完全操作,否則隻能get讀取
]
}
視圖應用
views.py 普通中設定權限方法。
from rest_framework.permissions import *
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = [IsAuthenticated|IsAuthenticatedOrReadOnly]
def get(self, request, format=None):
content = {
'status': 'request 被允許'
}
return Response(content)
views.py 裝飾器設定權限方法。
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)
其他權限類型
權限類型 DjangoModelPermissions
該權限類與 Django 的标準 django.contrib.auth 模型權限相關聯,隻能應用于 .queryset 屬性的視圖。
僅當使用者通過身份驗證并配置設定了相關的模型權限時,才會授權。
- POST 請求需要使用者對 add 模型具有權限。
- PUT、PATCH 請求要求使用者對 change 模型具有權限。
- DELETE 請求需要使用者對 delete 模型具有權限。
DjangoModelPermissionsOrAnonReadOnly
與 DjangoModelPermissions 相似,允許未經身份驗證的使用者對 API 進行隻讀通路。
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
DjangoObjectPermissions
與 DjangoModelPermissions 相似,該權限類與 Django 的标準對象權限架構相關聯,允許對模型進行按對象劃分的權限,使用此權限類需要添加一個支援對象級權限的權限後端 django-guardian。
将 django-guardian 用作對象級權限後端需要考慮使用 djangorestframework-guardian 包提供的DjangoObjectPermissionsFilter 類確定清單端點隻傳回結果。
安裝三方插件。
pip install django-guardian
settings.py 中添加配置應用。
INSTALLED_APPS = [
......
'guardian',
]
# guardian作為額外的授權BACKEND添加進配置
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'guardian.backends.ObjectPermissionBackend',
)
生成表單guardian_groupobjectpermission和guardian_userobjectpermission,用于記錄了使用者/組與model以及model内的具體object的權限對應關系。
python manage.py migrate
權限的自定義舉例
自定義權限需要重寫 BasePermission 。
- .has_permission(self, request, view)
- .has_object_permission(self, request, view, obj)
方法應傳回 True 應授予請求通路權限, 否則則傳回 False。
class MyPermission(BasePermission):
message = '自定義的傳回資訊'
def has_permission(self, request, view): # 清單資料
# # 這個函數傳回True或者False,True表示有權限,False表示沒有權限,這個函數同時有三個參數,最後一個是view, 這個是在源碼中規定的
# if request.user.id == 0:
# return False
# else:
return True
def has_object_permission(self, request, view, obj): # 對象資料
"""使用者是否有權限通路添加了權限控制類的資料對象"""
# 需求:使用者能夠通路id為1,3的對象,其他的不能夠通路
if request.user.is_active == 1:
return True
else:
return False