JWT拓展的登入檢視中, 在接受到使用者名稱和密碼時, 呼叫的也是Django的認證系統中提供的authenticate()來檢查使用者名稱與密碼是否正確.
我們可以通過修改Django系統的認證後端來支援登入賬號既可以是使用者名稱
也可以是手機號
修改重寫思路是:
修改Django認證系統的認證後端需要繼承django.contrib.auth.backends.ModelBackends, 並重寫authenticate方法
我們需要重寫什麼位置?
因為我們的需求是多條件登入, 所以我們就應該著手於資料庫校驗操作, 尋找定位原始碼中資料庫校驗username是否存在的操作, 並使用Q查詢新增多個條件驗證
下面是以from rest_framework_jwt.views import obtain_jwt_token
為入口進行的原始碼分析(序號為查詢流程):
繼承JsonWebTokenAPIView檢視, 當接受到使用者post請求時, 執行get_serializer()
呼叫get_serializer()方法找到子類中定義的serializer類
當呼叫is_valid()方法時, 會呼叫到validate()
這裡呼叫了authenticate方法並傳入了使用者資料, 返回的物件user
在utils/authenticate.py中:
from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q
def get_user_by_account(account):
"""
根據帳號資訊獲取user模型範例物件
:param account: 賬號資訊,可以是使用者名稱,也可以是手機號,甚至其他的可用於識別使用者身份的欄位資訊
:return: User物件 或者 None
"""
user = UserModel.objects.filter(Q(mobile=account) | Q(username=account) | Q(email=account)).first()
return user
class CustomAuthBackend(ModelBackend):
"""
自定義使用者認證類[實現多條件登入]
"""
def authenticate(self, request, username=None, password=None, **kwargs):
"""
多條件認證方法
:param request: 本次使用者端的http請求物件
:param username: 本次使用者端提交的使用者資訊,可以是user,也可以mobile或其他唯一欄位
:param password: 本次使用者端提交的使用者密碼
:param kwargs: 額外引數
:return:
"""
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
if username is None or password is None:
return
# 根據使用者名稱資訊useranme獲取賬戶資訊
user = get_user_by_account(username)
if user and user.check_password(password) and self.user_can_authenticate(user):
return user
在組態檔settings/dev.py中告知Django使用我們自定義的認證後端,注意不是給drf新增設定。
# django自定義認證
AUTHENTICATION_BACKENDS = ['luffycityapi.utils.authenticate.CustomAuthBackend', ]
本文來自部落格園,作者:{Max},僅供學習和參考