Django restframework用戶許可權認證組件增加及源碼分析

来源:https://www.cnblogs.com/aitiknowledge/archive/2020/06/01/13026295.html
-Advertisement-
Play Games

用戶許可權驗證源碼剖析,和用戶登錄驗證有點相似,但是為了增加記憶,有必要再一次添加, 註意:一定要跟著博主的解說再看代碼的中文註釋及其下麵的一行代碼!!! 1、準備一個路由和視圖類,全局路由配置暫時忽略,當流程執行到下麵的url:groupsSelectAll——> GroupsView的視圖類下的a ...


用戶許可權驗證源碼剖析,和用戶登錄驗證有點相似,但是為了增加記憶,有必要再一次添加,

註意:一定要跟著博主的解說再看代碼的中文註釋及其下麵的一行代碼!!!

1、準備一個路由和視圖類,全局路由配置暫時忽略,當流程執行到下麵的url:groupsSelectAll——> GroupsView的視圖類下的as_view()方法

from django.conf.urls import url

from . import views


app_name = '[words]'
urlpatterns = [
    url(r'groupsSelectAll/', views.GroupsView.as_view(), name="groupsSelectAll"),   # 片語信息查詢所有

]
class GroupsView(APIView):

    def get(self, request):
        conditions = {
            "id": request.query_params.get("wid"),
            "name": request.query_params.get("name"),
            "start_time": request.query_params.get("start_time"),
            "end_time": request.query_params.get("end_time"),
        }
        res = DataManager.select_by_conditions("words_groups", None, **conditions)
        return Response(data={"code": 200, "result": res})

2、但是GroupsView類下沒有as_view方法,這時就要去它的父類APIView查看(點進去看as_view方法),這裡博主只複製方法源代碼,大家只需要看中文註釋及其下的代碼語句。在這個方法中值得一提的是super關鍵字,如果請求視圖類(就是GroupsView類,如果繼承了多個父類)還有另一個父類,它先會查看這個父類是否有as_view方法。在這裡它是會執行APIView的父類View中的as_view方法,然後我們再次查看父類View的as_view方法。第一個as_view方法是APIView類的,第二個as_view方法是View類的。

    @classmethod
    def as_view(cls, **initkwargs):
        """
        Store the original class on the view function.

        This allows us to discover information about the view when we do URL
        reverse lookups.  Used for breadcrumb generation.
        """
        if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
            def force_evaluation():
                raise RuntimeError(
                    'Do not evaluate the `.queryset` attribute directly, '
                    'as the result will be cached and reused between requests. '
                    'Use `.all()` or call `.get_queryset()` instead.'
                )
            cls.queryset._fetch_all = force_evaluation

        # 執行父類的as_view方法
        view = super(APIView, cls).as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs

        # Note: session based authentication is explicitly CSRF validated,
        # all other authentication is CSRF exempt.
        return csrf_exempt(view)
APIView.as_view()
@classonlymethod
    def as_view(cls, **initkwargs):
        """Main entry point for a request-response process."""
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        # 執行view方法
        def view(request, *args, **kwargs):
            # 這裡的cls就是我們的請求視圖類,顯而易見,這個self是請求試圖類的對象
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            # 然後這裡就是執行dispatch方法
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view
View.as_view()

3、我們在第二個as_view方法中可以知道self是我們的請求視圖類的對象,通過這個self調用dispatch方法,請求視圖類中沒有dispatch方法,是不是又去APIView類中執行dispatch方法。

def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        # 這裡是對原生的request加工處理,返回一個新的request對象
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            # 初始化(用戶登錄認證,許可權驗證,訪問頻率限制)
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                # 通過python的反射機制反射到請求視圖類的方法名稱
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            
            # 最後就是執行請求視圖類的方法
            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
APIView.dispatch()

4、其他代碼不用看,我們直接看initial方法,因為這個initial方法有許可權驗證的功能。

def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        # 用戶驗證的方法,這個request 是加工之後的request
        self.perform_authentication(request)
        # 用戶許可權驗證
        self.check_permissions(request)
        # 用戶訪問頻率限制
        self.check_throttles(request)
APIView.initial()

5、這就到了我們的用戶許可權驗證的戲碼了。博主添加APIView部分代碼,即check_permission方法用到的代碼。我們可以查看代碼中的self.check_permissions(request),點進去查看check_permissions()方法,可以看到有get_permissions方法,這個方法有self.permission_classes變數,即self.permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES,然後這裡也和【上一篇的用戶登錄驗證】很相似,就是請求視圖類中如果沒有這個變數名及值(值是一個列表),就會使用全局配置文件中的REST_FRAMEWORK={"DEFAULT_PERMISSION_CLASSES":["許可權驗證類的全路徑"]},或者我們在請求視圖類中添加這個變數及值

class APIView(View):

    # 如果請求視圖類中沒有這個變數和值,就會使用全局配置文件的值
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES

    def check_permissions(self, request):
        """
        Check if the request should be permitted.
        Raises an appropriate exception if the request is not permitted.
        """
        # 迴圈許可權類的對象
        for permission in self.get_permissions():
            # 執行對象下的has_permission()方法,驗證是否有許可權(預設是有許可權)
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request, message=getattr(permission, 'message', None)
                )

    def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        # 返回的是一個許可權類的對象
        return [permission() for permission in self.permission_classes]

    def permission_denied(self, request, message=None):
        """
        If request is not permitted, determine what kind of exception to raise.
        """
        # 有許可權類,但是沒有登錄,就拋出用戶沒有登錄的異常
        if request.authenticators and not request.successful_authenticator:
            raise exceptions.NotAuthenticated()
        # 拋出沒有許可權的異常
        raise exceptions.PermissionDenied(detail=message)
APIView

6、在上面的APIView類中會執行到if not permission.has_permission(request, self),我們可以直接點進去查看has_permission方法。一般我們自定義這個用戶許可權驗證類的話我們一般需要繼承BasePermission類,這樣我們直接重寫has_permission方法,裡面的需求就是驗證時候當前登錄的用戶是否具有某個模塊的許可權。像這樣我們可以自定義一個只有充值稱為VIP或者SVIP用戶訪問許可權的類(這隻是我的設想)

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.補全代碼的聲明:alt + / 2.快速修複: ctrl + 1 3.批量導包:ctrl + shift + o 4.使用單行註釋:ctrl + / 5.使用多行註釋: ctrl + shift + / 6.取消多行註釋:ctrl + shift + \ 7.複製當前行的代碼上下移動:或 ctr ...
  • 本教程源碼請訪問:tutorial_demo 一、什麼是動態代理 1.1、概念 動態代理的用途與裝飾模式很相似,就是為了對某個對象進行增強。所有使用裝飾者模式的案例都可以使用動態代理來替換。 特點:位元組碼隨用隨創建,隨用隨載入; 作用:不修改源碼的基礎上對方法增強; 學習目的:為了學習AOP的原理做 ...
  • 題目:有一分數序列:2/1,3/2,5/3,8/5,13/8,21/13...求出這個數列的前20項之和。 程式分析:請抓住分子與分母的變化規律。 實例: 1 #include <stdio.h> 2 3 int main() 4 { 5 int i,t; 6 float sum=0; 7 floa ...
  • 題目:列印出如下圖案(菱形)。 * *** ***** ******* ***** *** * 程式分析:先把圖形分成兩部分來看待,前四行一個規律,後三行一個規律,利用雙重for迴圈,第一層控制行,第二層控制列。 實例: 1 #include <stdio.h> 2 int main() 3 { 4 ...
  • 演算法定義: 冒泡排序(Bubble Sort),是一種電腦科學領域的較簡單的排序演算法。 它重覆地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果順序(如從大到小、首字母從Z到A)錯誤就把他們交換過來。走訪元素的工作是重覆地進行直到沒有相鄰元素需要交換,也就是說該元素列已經排序完成。 這個演算法的名 ...
  • func ProxyTest() { proxyAddr := "http://your IP:8080/" httpUrl := "http://your target url" poststr := "your post values" proxy, err := url.Parse(proxy ...
  • 1、生產者、消費者 操作系統(生產者、消費者問題) 2、管程法 (1)創建生產者: public class Productor extends Thread{ SynContainer synContainer; public Productor(SynContainer synContainer ...
  • 作者:勿念先生 https://blog.csdn.net/moHedong/java/article/details/79687878 GC的歷史比Java還有久遠,我們在思考GC時候需要思考三個問題: 哪些記憶體需要回收? 什麼時候回收? 如何回收? 在Java中程式計數器、虛擬機棧、本地方法棧這 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...