前言
上一篇我們分析了認證的原始碼,一個請求認證通過以後,第二步就是檢視許可權了,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]
屬與區域性配置,也就是自定義的許可權只針對此檢視,其他檢視還是預設的全域性配置,如果我們還有其他的關於許可權的需求,只需要在自定義的許可權類中寫邏輯即可