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(內部循環....)