rest_framework-01-認證(用戶登錄)-內置認證
如果我們寫API有人能訪問,有人不能訪問,則需要些認證。
如何知道該用戶是否已登入?
如果用戶登入成功,則給用戶一個隨機字符串,去訪問另一個頁面。
以前寫session的時候,都是把session寫cookie里面。
那現在我們可以把隨機字符串通過返回值的方式給用戶。
后端通過查看用戶的url判斷用戶有沒有token值且這個字符串是否正確也要判斷。有則已登入,可以訪問;沒有則跳回登入頁面。
用戶登入
1.有些api需要用戶登入才能訪問,有些api不需要用戶登入就能訪問。
1.api(app應用) > models.py: 表

2.創建表數據:用戶表

3.urls.py

4.views.py:用戶登入只有post請求!!!

5.token用md5加密,並保存或更新到數據庫中。


6.post請求,運行結果:

7.token就保存到數據庫了。

8.token生成成功后,就將新的token返回給用戶。有異常則返回異常。API寫完了。

views.py:API寫完了。

運行結果:

小結:解決: a. 創建兩張表 。b. 用戶登錄(返回token並保存到數據庫)。
認證
用戶所有訂單api
1.訂單url

2.views.py訂單視圖
假設這是所有訂單數據


3.運行結果:get請求

4.如果這個訂單只有登入成功的時候才可以看,你會怎么解決???

運行結果:

rest_framework認證
5.這段代碼假設post請求也要認證,如果再復制一遍就會很冗余。django已經幫我們封裝好了,不用自己寫。

6.自定義一個認證類,自己寫認證規則。

7.認證源碼:

8.自己定義認證規則,認證失敗則返回一個異常。


9.注意:必須再寫一個方法,否則還會報錯。
引入該模塊, 加上該方法:先為空。

查看該模塊源碼:

加上該方法:先為空。

注釋一下代碼:

運行結果:

用戶信息api
1.假設用戶信息api也要認證,(登入后才能訪問),怎么辦呢?
自定義的一個認證寫完了之后,api視圖加上就好了。

2.如果有成千上萬個api都需要認證怎么辦呢??? 接下來全局認證。(不需要每一個視圖都自己加上以上代碼)全局配置settings.py。
認證源碼流程圖:

源碼配置:
1.dispatch

2.封裝Request

3.for循環認證列表

4.默認去全局的配置文件讀

5.如果自己請求函數里面設置了,就用自己的。沒設置就用配置文件的。
6.將認證寫在配置文件中,不用局部的。
源碼:
api_settings表示去配置文件中讀。

讀 REST_FRAMEWORK 這個key

7.setting.py

8.將認證相關的東西都寫在一個文件中。再引入該文件。

settings.py
REST_FRAMEWORK = { # 全局使用的認證類 "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FrstAuthtication','api.utils.auth.Authtication'], }
views.py:視圖文件中只有視圖相關的類。

9.列表里填你自己寫的認證類的路徑。 view.py里的所有類都不用加了,默認用session全局的認證。

10.登入不需要認證信息。全局認證,個別不需要認證。
空列表就行

11.運行結果:
訂單接口:

登入接口:

訂單接口:

request封裝完了(認證配置),接下來繼續看源碼。
0.request封裝

1.讀取全局認證配置

2.進行認證

3.initial > 實現認證self.perform_authentication(request)

4.user

5.獲取認證對象,進行下一步步的認證

往下走


6.如果是匿名用戶,默認叫什么
setting.py

views.py

urls.py

運行結果:

7.源碼設置默認用戶名:

8.設置匿名用戶名
"UNAUTHENTICATED_USER":lambda :"匿名用戶"
匿名函數沒有參數,直接返回字符串

url請求:

運行結果:

9.setting.py:


內置認證
1.django內置的認證在哪呢?引入BaseAuthentication
from rest_framework.authentication import BaseAuthentication

BaseAuthentication源碼:
1.

2.BaseAuthentication 下有兩個方法。

3.推薦繼承BaseAuthentication。更規范。

代碼:
from rest_framework import exceptions from api import models from rest_framework.authentication import BaseAuthentication # 用戶認證 class FrstAuthtication(BaseAuthentication): def authenticate(self,request): pass def authenticate_header(self, request): pass class Authtication(BaseAuthentication): def authenticate(self,request): token = request._request.GET.get('token') token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: # 未登入或者是錯誤的token raise exceptions.AuthenticationFailed('用戶認證失敗!') # 認證成功。在rest_framework內部會將整個兩個字段賦值給request,以供后續操作使用。 return (token_obj.user,token_obj) def authenticate_header(self, request): pass
接下來繼續走源碼: BasicAuthentication 基於留言器認證

1.往下走,復制源碼

2.設置請求頭的返回值為api

settings.py

運行結果:

3.views.py: 引入BasicAuthentication

4.運行結果:

5.看源碼

6.改源碼,先注釋一下2行代碼

不注釋表示允許用戶為匿名用戶。

7.運行結果:瀏覽器會對用戶名和密碼加密放到url上,然后發給服務端,進行驗證。

8.還原代碼:

BasicAuthentication原理:

小結:
今日內容: 1. 認證 a. 問題1:有些API需要用戶登錄成功之后,才能訪問;有些無需登錄就能訪問。 b. 基本使用認證組件 解決: a. 創建兩張表 b. 用戶登錄(返回token並保存到數據庫) c. 認證流程原理 - 見圖示 d. 再看一遍源碼 1. 局部視圖使用&全局使用 2. 匿名是request.user = None e. 內置認證類 1. 認證類,必須繼承:from rest_framework.authentication import BaseAuthentication 2. 其他認證類:BasicAuthentication 梳理: 1. 使用 - 創建類:繼承BaseAuthentication; 實現:authenticate方法 - 返回值:3種返回值 - None,我不管了,下一認證來執行。 - raise exceptions.AuthenticationFailed('用戶認證失敗') # from rest_framework import exceptions - (元素1,元素2) # 元素1賦值給request.user; 元素2賦值給request.auth - 局部使用 from rest_framework.authentication import BaseAuthentication,BasicAuthentication class UserInfoView(APIView): """ 訂單相關業務 """ authentication_classes = [BasicAuthentication,] def get(self,request,*args,**kwargs): print(request.user) return HttpResponse('用戶信息') - 全局使用: REST_FRAMEWORK = { # 全局使用的認證類 "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication', ], # "UNAUTHENTICATED_USER":lambda :"匿名用戶" "UNAUTHENTICATED_USER":None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None } 2. 源碼流程 - dispatch - 封裝request - 獲取定義的認證類(全局/局部),通過列表生成時創建對象。 - initial - perform_authentication request.user(內部循環....)
