與 authentication 和 throttling 一起,permission 決定是應該接受還是拒絕訪問請求。
權限檢查總是在視圖的最開始處運行,在任何其他代碼被允許進行之前。權限檢查通常會使用 request.user 和 request.auth 屬性中的認證信息來確定是否允許傳入請求。
權限用於授予或拒絕不同類別的用戶訪問 API 的不同部分。
最簡單的權限是允許通過身份驗證的用戶訪問,並拒絕未經身份驗證的用戶訪問。這對應於 REST framework 中的 IsAuthenticated 類。
稍微寬松的權限會允許通過身份驗證的用戶完全訪問,而未通過身份驗證的用戶只能進行只讀訪問。這對應於 REST framework 中的 IsAuthenticatedOrReadOnly 類。
設置權限策略
默認權限策略可以使用 DEFAULT_PERMISSION_CLASSES setting 全局設置。例如
REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
如果未指定,則此設置默認為允許無限制訪問:
'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.AllowAny', )
當然也可以基於 APIView 類的視圖上設置身份驗證策略
查看源碼,restframework現成的類有7個,介紹如下常用四個
AllowAny:允許無限制訪問
IsAuthenticated :允許訪問任何經過身份驗證的用戶,並拒絕訪問任何未經身份驗證的用戶
IsAdminUser:允許超級用戶訪問
IsAuthenticatedOrReadOnly:對經過身份驗證的用戶的允許完全訪問,但對未經身份驗證的用戶的允許只讀訪問
@six.add_metaclass(BasePermissionMetaclass) class BasePermission(object): """ A base class from which all permission classes should inherit. """ def has_permission(self, request, view): """ Return `True` if permission is granted, `False` otherwise. """ return True def has_object_permission(self, request, view, obj): """ Return `True` if permission is granted, `False` otherwise. """ return True
但完全可以我們自己來寫,僅需要面向上述源碼任意一個接口即可。
apps/app/permissions.py
from rest_framework.permissions import BasePermission class IsLoginReadOnly(BasePermission): """ 自定義權限設置 """ def has_permission(self,request,view): return all((request.user.is_authenticated,request.user.is_staff))
如果你需要測試請求是讀取操作還是寫入操作,則應該根據常量SAFE_METHODS
檢查請求方法,SAFE_METHODS
是包含'GET'
, 'OPTIONS'
和'HEAD'
的元組
if request.method in permissions.SAFE_METHODS: # 檢查只讀請求的權限 else: # 檢查讀取請求的權限
views.py
from rest_framework import mixins from rest_framework import viewsets from .models import UserProfile from .serializers import UserProfileSerializer from .permissions import IsAuthenticatedOrReadOnly class UsersListViewSets(viewsets.GenericViewSet,mixins.ListModelMixin): """ 用戶列表 """ queryset = UserProfile.objects.all() serializer_class = UserProfileSerializer permission_classes = (IsAuthenticatedOrReadOnly,)
對象級權限
實際場景下,我們往往需要對權限細分:
POST 請求要求用戶對模型實例具有 add 權限。
PUT 和 PATCH 請求要求用戶對模型實例具有 edit 權限。
DELETE 請求要求用戶對模型實例具有 delete 權限。
這就需要我們重寫APIView下的has_permissions方法
views.py
from .permission import UserAddPermission from .permission import UserDeletePermission from .permission import UserEditPermission from .permission import UserQueryPermission # permission_classes = (UserQueryPermission,) def get_permissions(self): if self.action == "create": self.permission_classes = (UserAddPermission,) elif self.action == "list": self.permission_classes = (UserQueryPermission,) elif self.action == "update": self.permission_classes = (UserEditPermission,) elif self.action == "destroy": self.permission_classes = (UserDeletePermission,) return super().get_permissions()
permission.py
class UserAddPermission(BasePermission): """ 增加用戶權限 """ def has_permission(self, request ,view): user = request.user if user.is_authenticated: permissons = user.has_permissons() return "add user" in permissons
遇到了問題,即使UsersListViewSets繼承了viewsets.ModelViewSet,該接口依舊只允許GET, POST, HEAD, OPTIONS四種方法,
沒有put和delete.
解決:自己手動綁定。。。
def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) def delete(self,request, *args, **kwargs): return self.destroy(request, *args, **kwargs)