Django contrib auth authenticate函數(shù)源碼解析
引言
django提供了一個(gè)默認(rèn)的auth系統(tǒng)用于用戶的登錄和授權(quán),并提供了一定的擴(kuò)展性,允許開(kāi)發(fā)者自行定義多個(gè)驗(yàn)證后臺(tái),每個(gè)驗(yàn)證后臺(tái)必須實(shí)現(xiàn)authenticate函數(shù),并返回None或者User對(duì)象。
默認(rèn)的后臺(tái)是django.contrib.auth.backends.ModelBackend,該后臺(tái)通過(guò)用戶名和密碼進(jìn)行用戶的驗(yàn)證,以settings.AUTH_USER_MODEL作為模型。但是在實(shí)際的開(kāi)發(fā)中,相信大家都不會(huì)固定的使用用戶名以及同一個(gè)model進(jìn)行驗(yàn)證,比如,不同的角色需要不同的model作為驗(yàn)證的數(shù)據(jù)源,有的角色是使用手機(jī)登錄,而有的角色使用郵箱登錄。
那么,當(dāng)存在多個(gè)驗(yàn)證后臺(tái)的時(shí)候,django是如何制作一個(gè)統(tǒng)一的接口進(jìn)行不同后臺(tái)的驗(yàn)證呢?
authenticate函數(shù)分析
源碼:
def authenticate(**credentials): """ If the given credentials are valid, return a User object. """ for backend, backend_path in _get_backends(return_tuples=True): try: inspect.getcallargs(backend.authenticate, **credentials) except TypeError: # This backend doesn't accept these credentials as arguments. Try the next one. continue try: user = backend.authenticate(**credentials) except PermissionDenied: # This backend says to stop in our tracks - this user should not be allowed in at all. break if user is None: continue # Annotate the user object with the path of the backend. user.backend = backend_path return user # The credentials supplied are invalid to all backends, fire signal user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials))
**credentials
首先可以看到authenticate函數(shù)接受的參數(shù),這是指authenticate函數(shù)只接受關(guān)鍵字傳參,位置傳參是不允許的。因此在使用authenticate函數(shù)的時(shí)候注意不要為了省事而位置傳參。
# This will fail
user = authenticate('username', 'password')# This will success
user = authenticate(username='username', password='password')
inspect.getcallargs(func, *args, **kwargs)
inspect模塊是Python官方的標(biāo)準(zhǔn)模塊,這個(gè)模塊對(duì)Python的自省功能進(jìn)行一定的封裝。其中inspect.getcallargs檢查args和kwargs這些參數(shù)是否能被func要求的參數(shù)匹配,若匹配成功返回參數(shù)字典,如果不能匹配就會(huì)raise TypeError。
舉個(gè)簡(jiǎn)單的例子。假設(shè)在Python中定義這樣一個(gè)函數(shù):
import inspect def test_func(arg1, arg2, *args, **kwargs): pass # this will raise TypeError inspect.getcallargs(test_func, a=1, b=2, c=3) # TypeError: test_func() missing 2 required positional arguments: 'arg1' and 'arg2' # this will ok inspect.getcallargs(test_func, 1, 2, 3, a=1, b=2, c=3) # {'kwargs': {'b': 2, 'c': 3, 'a': 1}, 'arg2': 2, 'args': (3,), 'arg1': 1}
應(yīng)用場(chǎng)景
通過(guò)inspect.getcallargs的參數(shù)過(guò)濾功能,只要設(shè)置不同后臺(tái)的authenticate的函數(shù)參數(shù),就能在第一步實(shí)現(xiàn)不同角色的后臺(tái)選擇。
假設(shè)有三種角色,角色1使用用戶名登錄,角色2使用手機(jī)登錄,角色3使用手機(jī)或者郵箱登錄,那么如何通過(guò)inspect.getcallargs就選擇合適的backend.authenticate呢?
def role3_authenticate(role3_phone=None, role3_email=None, password=None): print("role1 authentication.") def role2_authenticate(role2_phone=None, password=None): print("role2 authenticate.") def role1_authenticate(role1_name=None, password=None): print("role2 authenticate.") methods = [role1_authenticate, role2_authenticate, role3_authenticate] def authenticate(**credentials): for backend in methods: try: inspect.getcallargs(backend, **credentials) except TypeError: print("error") continue backend(**credentials) print("end") break
如果加入**kwargs則每個(gè)authenticate都不會(huì)引發(fā)TypeError,因?yàn)槠溆鄥?shù)都設(shè)置了默認(rèn)參數(shù),如果確實(shí)需要,則之前的參數(shù)使用位置傳參。
signal
若用戶沒(méi)有成功登陸,則authenticate發(fā)送了一個(gè)用戶沒(méi)有成功登陸的信號(hào),開(kāi)發(fā)者可以自行定義接受這個(gè)信號(hào)的recevier。關(guān)于django signal筆者之后還會(huì)詳細(xì)談及。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
利用python檢查磁盤(pán)空間使用情況的代碼實(shí)現(xiàn)
本文將向讀者展示如何利用Python編寫(xiě)自動(dòng)化腳本,以檢查磁盤(pán)空間使用情況,無(wú)論你是經(jīng)驗(yàn)豐富的系統(tǒng)管理員,還是對(duì)Python自動(dòng)化充滿興趣的開(kāi)發(fā)者,本文都將為你提供實(shí)用的腳本示例和詳細(xì)的解析步驟,幫助你快速掌握磁盤(pán)空間監(jiān)控的自動(dòng)化方法,需要的朋友可以參考下2024-08-08python實(shí)現(xiàn)二次元圖片展示(屏保)
這篇文章主要介紹了python實(shí)現(xiàn)二次元圖片展示,用了API端口相關(guān)的知識(shí)實(shí)現(xiàn),下面詳細(xì)的文章內(nèi)容需要的小伙伴可以參考一下2022-02-02freeswitch開(kāi)源通信 python模塊介紹
freeswitch支持多種語(yǔ)言的業(yè)務(wù)開(kāi)發(fā),包括C/C++,java,python,js,lua,Golang等等。freeswitch在使用python做業(yè)務(wù)開(kāi)發(fā)時(shí),有倆種接入方式,一種是ESL接口,另一種是mod_python模塊。本文主要介紹的是fs內(nèi)部的mod_python語(yǔ)言支持模塊,需要的朋友可以參考下面文章內(nèi)容2021-09-09解決python刪除文件的權(quán)限錯(cuò)誤問(wèn)題
下面小編就為大家分享一篇解決python刪除文件的權(quán)限錯(cuò)誤問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-04-04Django模塊學(xué)習(xí)之模塊語(yǔ)言詳解
模板語(yǔ)言渲染的整個(gè)過(guò)程其實(shí)就是將html轉(zhuǎn)換成函數(shù),并為該函數(shù)提供全局變量,然后執(zhí)行該函數(shù),下面這篇文章主要給大家介紹了關(guān)于Django模塊學(xué)習(xí)之模塊語(yǔ)言的相關(guān)資料,需要的朋友可以參考下2021-11-11