Django(63)drf許可權源碼分析與自定義許可權
前言
上一篇我們分析了認證的源碼,一個請求認證通過以後,第二步就是查看許可權了,drf默認是允許所有用戶訪問
許可權源碼分析
源碼入口:APIView.py文件下的initial方法下的check_permissions
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)
)
許可權在get_permissions方法中獲取到,源碼如下:
def get_permissions(self):
"""
實例化並返回此視圖所需的許可權列表。
"""
return [permission() for permission in self.permission_classes]
permission_classes又等於api_settings.DEFAULT_PERMISSION_CLASSES,所以我們去settings.py文件中查找
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
我們會發現drf默認的許可權是AllowAny,我們去看下源碼:
class AllowAny(BasePermission):
"""
允許任意訪問。這不是嚴格要求的,因為您可以使用空的 permission_classes 列表,但它很有用,因為它使意圖更加明確。
"""
def has_permission(self, request, view):
return True
我們可以看到AllowAny繼承自BasePermission,然後定義了has_permission方法,返回值為True。
drf為我們提供了4個系統許可權認證:
1. AllowAny
認證規則全部返回True:`return True`
遊客與登錄用戶都有所有許可權
2. IsAuthenticated
認證規則必須有登錄的合法用戶:`return bool(request.user and request.user.is_authenticated)`
遊客沒有任何許可權,登錄用戶才有許可權
3. IsAdminUser
認證規則必須是:`return bool(request.user and request.user.is_staff)`
遊客沒有任何許可權,登錄用戶才有許可權
4. IsAuthenticatedOrReadOnly
認證規則必須是只讀請求或者是合法用戶無限制
return bool(
request.method in SAFE_METHODS or
request.user and
request.user.is_authenticated
)
遊客只讀,合法用戶無限制
自定義認證類
- 創建繼承
BasePermission的許可權類 - 實現
has_permission方法 - 實現體根據許可權規則 確定 有無許可權
- 進行全局或局部配置(一般採用局部配置)
許可權規則
滿足設置的用戶條件,代表有許可權,返回True
不滿足設置的用戶條件,代表有許可權,返回False
自定義許可權
from django.contrib.auth.models import Group
from rest_framework.permissions import BasePermission
class MyPermissions(BasePermission):
def has_permission(self, request, view):
rule1 = request.method in ['GET', 'OPTIONS', 'HEAD']
group = Group.objects.filter(name="管理員").first()
groups = request.user.groups.all()
rule2 = group in groups
rule3 = group and groups
return rule1 or (rule2 and rule3)
以上定義了3條規則
- rule1:請求方法是
GET、OPTIONS、HEAD遊客和用戶都可以訪問 - rule2:當前用戶如果有多個分組,其中必須有一個分組是管理員
- rule3:管理員分組必須存在,用戶必須在分組中
接下里我們定義視圖
class TestView(APIView):
permission_classes = [MyPermissions]
def get(self, request, *args, **kwargs):
print(request.user)
return APIResponse(data_msg="所有用戶都可以訪問")
def post(self, request, *args, **kwargs):
print(request.user)
return APIResponse(data_msg="只有管理員用戶可以訪問")
視圖中只是添加了permission_classes = [MyPermissions]屬與局部配置,也就是自定義的許可權只針對此視圖,其他視圖還是默認的全局配置,如果我們還有其他的關於許可權的需求,只需要在自定義的許可權類中寫邏輯即可

