Django REST Framework之權限組件

  • 2019 年 10 月 3 日
  • 筆記

權限控制是如何實現的?

一般來說,先有認證才有權限,也就是用戶登錄後才能判斷其權限,未登錄用戶給他一個默認權限。

Django接收到一個請求,首先經過權限的檢查,如果通過檢查,擁有訪問的權限,則予以放行,進入到視圖處理。如果沒有通過檢查,不會進入視圖層,直接返回前端相應信息。

使用權限控制

權限控制類:

class MyPermission(BasePermission):      message = "您沒有權限"        def has_permission(self, request, view):          # 判斷用戶是否有權限,邏輯自己定義。返回值為True或False,代表擁有權限或沒有權限          user_obj = request.user          if user_obj.type == 3:              return False          else:              return True

views.py:

from rest_framework.views import APIView  from utils.permission import MyPermission    class TestView(APIView):      permission_classes = [MyPermission, ] # 使用該權限控制,可以同時使用多個權限控制類        def get(self, request, *args, **kwargs):          pass           def post(self, request, *args, **kwargs):          pass            '''          等等一系列的視圖功能方法          '''

全局權限控制:

settings.py

REST_FRAMEWORK = {      "DEFAULT_PERMISSION_CLASSES" :['utils.permission.Mypermission',]  }

注意:如果有部分類不需要權限判斷的話,可以在Mypermission類中添加“permission_classes = []”,即可

源碼分析

其實權限的源碼流程跟認證的流程基本相同。還是要抓住通過源碼要想知道什麼,不然就會陷入浩如煙海的源碼之中。

1.為什麼會使用permission_classes屬性變量?

python 的面向對象編程中,我們首先要執行的方法肯定是dispatch方法,所以我們的分析入口就是dispatch方法,在dispatch方法中,可以看到,通過initialize_request方法將django原生的request進行了一次封裝。由initialize_request方法的實現過程可以看出,將其封裝實例化成了一個Request對象。但權限判斷並沒有像認證一樣初始化到了Request對象中,但對django原生的request封裝還是需要強調的,因為編寫代碼的過程中對django原生的request的使用是必不可免的。

同樣的,權限判斷的具體過程跟認證一樣,也是在dispatch方法中所調用的initial方法中實現。再跳轉到initial方法中去。

在initial方法中,可以看到權限判斷的方法,沒錯,就是通過check_permissions方法實現的。再跳轉到這個方法中去。

在check_permissions方法中,就可以看到權限的判斷就是通過這個for循環實現的。正因為在業務代碼中可能存在若干種類型的權限判斷,所以才會通過循環去執行我們定義好的權限判斷類來完成多個權限體系的判斷功能。這樣,我們可以感覺到這裡的“self.get_permissions()”的返回值應該就是我們在視圖類中賦值過的permissions_classes屬性變量的值。那就跳轉到這個方法中去看看吧。

在get_permissions方法中看到,跟認證一樣,返回值同樣是一個列表生成式,而這個列表生成式使用的屬性變量正是我們賦值過的permission_classes,跟我們之前的猜測完全一致。綜上所述,我們為了讓drf接口源碼使用上我們自己定義的權限判斷類,那我們就必須按照源碼中寫的借口,將permission_classes屬性變量賦值

2.在權限判斷類中為什麼會定義一個名稱為has_permission的方法?

回到check_permissions方法中,我們看if判斷句,前面剛剛說過,在for中的permission其實就是我們自己定義的權限判斷類,那麼在if句中的“.has_permission(request,self)”不就應該就是Mypermission類中的方法嗎?所以,我們自己定義的Mypermission類中一定要實現has_permission這個方法。(要注意這個方法的參數)

3.has_permission方法中,為什麼返回值為布爾值?

還是跟上一個問題一樣的,在上圖中的if句中,我們可以看到“permission.has_permission(request, self)”的返回值不就是布爾值嗎,這個返回值不就是has_permission方法返回值嗎?當返回值為False時,就會執行if句中的代碼,來拋出異常。