與 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)
