# 課程鏈接
4天搞定django rest framework源碼和實戰_哔哩哔哩_bilibili
# 課程內容
(1)rest framework 之用戶登錄
(2)rest framework 之基於 token 實現基本用戶認證
(3)rest framework 之認證基本流程源碼分析
(4)rest framework 之匿名用戶配置
(5)rest framework 之內置基本認證
(6)rest framework 之認證內容總結
(7)rest framework 之權限的基本使用
【補充知識】
# 今朝有酒今朝醉
# (1)用戶登錄和本節主題
1)token 隨機字符串。這是用前端給後端發送用戶信息,然後後端對應生成一個隨機字符串,即 token。這個 token 可以放在請求頭或者 url 上面,最好是放在 url 上,這樣可以避免跨域問題。那麼這個 url 就比如下圖的。
2)本節主題。
# (2)用戶登錄的實現。
1)創建表數據,用於模擬流程。因為 username 只能是一個用戶對應一個用戶名,所以 UerInfo 表下的 username 屬性是唯一的。
2)設計好用戶表後,我們開始編寫視圖函數,來模擬用戶登錄的過程。總結來說就是,用戶向後端發送用戶名和密碼請求,後端接收後會在數據庫裡面核查,如果核查存在用戶,就會生成一個 token 保存在 UserToken 表下,並且將 token 返回給用戶。代碼如下。
3)token 的生成。這裡用到了 md5 加密的方法來生成,而且每一次用戶不管是否帶著 token 訪問,後端都會生成一個新的 token。 加密的代碼如下:
4)postman 的測試結果
# (1)用戶身份認證
1)有的頁面必須是用戶登錄後,才能操作。比如我們重新創建一個訂單業務的路由,編寫相應的視圖類。我們的思路就是判斷發來的用戶請求,是否帶有 token ,如果帶有 token,就說明用戶已經登錄了。
2)有兩種方式來實現這個思路(當然了,還有更加方便的)。第一種方法是直接在每一個函數中設置一個判斷 token 的邏輯,非常的麻煩。以下是驗證函數的 post 請求部分,我們加入的代碼邏輯。
# 測試的數據 ORDER_DICT = { 1: { "name": "lolo", "age": 12, "gender": "男" }, 2: { "name": "bobo", "age": 14, "gender": "男" } } class OrderView(APIView): """ 訂單業務 """ def get(self, request, *args, **kwargs): # 訂單頁面必須是已登錄的用戶才能看的, 顯然只要檢測用戶發送請求的時候是否帶了token即可。 # 基於這個思路,我們可以選擇兩種方來實現。 # (1) 第一種就是對每一個函數寫一個判斷。 # (2) 第二種是基於 drf 提供的方法來寫 # 以下是第一種 token = request._request.GET.get("token") if not token: # 如果 token 為空,那麼直接返回用戶未登錄 return HttpResponse("用戶未登錄") ret = {'code': 1000, 'msg': None, 'data': None} try: ret['data'] = ORDER_DICT except Exception as e: pass return JsonResponse(ret)
3)基於 drf 的驗證流程實現。首先要知道,如果要使用 drf 的源碼的流程中的authentication_classes,這個列表類裡面是放驗證規則的。這個規則可以是我們自己制定的。那麼具體的使用的話,就是得在每個函數裡面,提前配置好這個列表類,比如我們定義了一個驗證規則的類名是 Authentication,那麼我們要使用的時候,就是令authentication_classes = [ Authentication,] 。總之就是先這樣寫的,後面章節可以看源碼來做。
class OrderView(APIView): """ 訂單業務 """ # drf 的 authentication_classes 認證規則, 就是如果我們想要使用 drf 提供的登錄驗證的功能的話, # 就需要添加相應的規則給 authentication_classes, 然後這個規則,可以是我們自定義的 authentication_classes = [Authentication, ] def get(self, request, *args, **kwargs): # 訂單頁面必須是已登錄的用戶才能看的, 顯然只要檢測用戶發送請求的時候是否帶了token即可。 # 基於這個思路,我們可以選擇兩種方來實現。 # (1) 第一種就是對每一個函數寫一個判斷。 # (2) 第二種是基於 drf 提供的方法來寫 ret = {'code': 1000, 'msg': None, 'data': None} try: ret['data'] = ORDER_DICT except Exception as e: pass return JsonResponse(ret)
4)這裡給出驗證規則類的代碼。具體的注釋內容
from rest_framework import exceptions class Authentication(object): def authenticate(self, request): token = request._request.GET.get("token") token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: # 如果數據庫中沒有相應的 token 那麼就拋出異常,這個異常是 drf 自帶的,也必須是這麼寫的 raise exceptions.AuthenticationFailed("用戶認證失敗") # 如果認證成功,就返回下面的兩個值,封裝成元組的形式,這是給後續 drf 內部的源碼使用的 # 具體的就是給 self._authenticate() 函數下的 user_auth_tuple 使用 return (token_obj.user, token_obj.token) def authenticate_header(self, request): """因為定義的驗證類必須有這個方法,先暫時不管,後面會說。""" pass
# (1) 武sir 給的源碼流程
# (2)本人自己剖析的認證源碼流程
# (1)全局配置
1)我們可以看到,我們在第 (2) 節中說的,配置規則類 authentication_classes = [Authentication, ],這僅僅只是適用於當前的 OrderView 類中。其他的類如果沒有配置這個規則類,則不會使用。相當於局部配置而已。那麼如何進行全局配置(也就是即使所有的視圖類中沒有配置 authentication_classes ,也能用上我們自定義的規則類),就需要進行如下的步驟了。首先進入到 settings.py ,在最下面寫入 REST_FRAMEWORK = {} ,具體如下:
# (2)單獨的局部配置
1)基於上面的配置操作就可以設置,對全局的視圖類按照我們的自定義規則進行認證。當然有些視圖類並不需要這個認證,我們就可以單獨設置規則列表即可,那麼就是在視圖類中這樣配置(也就是局部配置),如下圖紅框所示。
# (1)內置基本認證規則
1)drf 中內置了基本的認證規則,比如 BaseAuthentication() 這個內置類。導入模塊 from rest_framework.authentication import BaseAuthentication 就可以使用了()也就是在 rest_framework 的 authentication 文件中。【這裡講解了為什麼自定義規則的時候,必須 authenticate_header()方法】
# (2)小總結
【復習】本節課的鏈接:4天搞定django rest framework源碼和實戰_哔哩哔哩_bilibili
# (1)內容總結
# (1)權限的基本使用
1)其實 drf 中權限的使用流程和前面的認證流程類似,並且相應的全局/局部配置也相似。比如說我們想要按照用戶的類型,來判斷該用戶是否有權限訪問某個視圖頁面。獲取用戶的類型很簡單,就是request.user.user_type ,如下面代碼,我們對每一個視圖類都進行一次判斷,這顯然很麻煩。
2)drf 提供的權限認證方法,其實應用的時候,也是和用戶認證的規則類差不多的。
3)具體的代碼,我們也可以看到,如果我們想對某個視圖類應用上自定義的權限規則的話,就可以跟之前用戶認證規則配置一樣即可。至於全局配置,見下節的源碼分析。
參考鏈接:4天搞定django rest framework源碼和實戰_哔哩哔哩_bilibili
【補充知識】
# (1)csrf 的原理
其實就是本文的第二個節。整個流程就是用戶登錄後,服務器給用戶返回一個 隨機字符串 token ,用戶下次訪問的時候,就帶著 token 來,如果服務器匹配了 token 則通過,否則訪問被拒絕。
參考資料:15天django入門到放棄_哔哩哔哩_bilibili