前言
如果你想要使用 Django REST framework(DRF) 與 JWT 快速實現一個能夠驗證使用者 email 與 password 的小型應用,在閱讀 DRF 官方文件時,官方推薦使用 🔗django-rest-framework-simplejwt 這個套件。
接著,你在跟著文件進行實作時感覺都沒有問題,可以很順利的 POST username 與 password 到後端,後端就會送一組 access
與 refresh
的 JWT token 給你,一切感覺都很美好。但是,也許突然你會有疑問:
如果我想要用 email 與 password 驗證可以嗎 ?
答案是可以的,而且實作上非常簡單。
快速建立 Django 與 DRF 的環境
在這個範例中,我們使用的套件版本如下:
- Django 2.2.6
- Django REST framework 3.10.3
- Django-rest-framework-simplejwt 4.3.0
安裝相依套件
首先,我們使用 pip 安裝相依套件,如果你不想讓弄髒環境,可以使用 virtualenv 隔離 Python 開發環境。
pip install django djangorestframework djangorestframework_simplejwt
建立 Django 環境
首先,我們先建立一個 django 的專案,專案名稱叫做 jwt-authentication。
django-admin startproject jwt-authentication
接著,則是用 Django 內建的 User 模組,建立一個使用者的帳號、信箱與密碼。別忘記在建立使用者以前要先 migrate。
python manage.py migrate
python manage.py createsuperuser
建立 Djangor REST framework 環境
因為在這個範例中,我們沒有要撰寫 DRF 的程式碼,所以初始化非常簡單,只要在 INSTALLED_APPS
中引入 rest_framework
及可。
建立 Django REST framwork simplejwt 環境
以下參考 🔗 simplejwt github
在這個範例中,DEFAULT_AUTHENTICATION_CLASSES
要加也可以,不加也可以,因為只是要實現用 email 與 password 也可以獲得 JWT 的 token,與權限機制沒有關係。
最後,在 urls.py
中註冊獲取 JWT token 的 api。
我們使用瀏覽器測試 api ,POST 剛剛建立的 username 與 password,可以看到系統回傳了一組 access
與 refresh
。
這時如果使用 email 與 password 獲取 JWT token 就會失敗,因為它原生要求的是輸入 username 與 password。
接下來,我們會對 Django 動一點手腳,讓 email 與 password 同樣可以獲得 JWT token。
修改 authentication backend 讓使用者可以用 email 與 password 進行驗證
當你想要修改驗證機制時,你會去看看 simplejtw 是不是有提供介面讓我們可以快速達成目的。
在網路上有些資料都會提到可以繼承 TokenObtainPairSerializer
這個類別,然後自訂義一個 custom serializer,修改驗證的方法。但是怕動到太多程式碼,所以後來跑去看了 TokenObtainPairSerializer
的原始碼,發現在這個類別中的 validate()
直接呼叫了父類別的 validate()
驗證方法。
接著,繼續往前追原始碼, TokenObtainSerializer
中的 validate()
驗證方法呼叫了 Django 原生 User 模組的 authenticate()
方法。所以,尋找方法修改 authenticate()
也許可以解決我們的問題。
from django.contrib.auth import authenticate
後來,在這篇 🔗stackoverflow 的問答中,其中一個回應就有提到如何修改 Django 提供的 authentication 介面。
修改 authentication 介面
沒想到 Django 提供了 authentication 的介面,所以我們只要自訂一個客製化的類別,就可以讓程式同時搜尋資料庫中的 username 與 email 達到我們的目的。
我們在 jwt_authentication 中新增 backend.py
,並在裡面定義客製化的類別:
在 settings.py
中修改 authentication 的介面變成我們寫的客製化類別:
使用 email 與 password 獲得 token
做完以上步驟後,再打開瀏覽器測試一次,終於,我們可以使用 email 與 password 成功獲得 token。
總結
在這篇文章中,我們使用的套件是官方推薦的 🔗simplejwt。simplejwt 使用的驗證方法是 Django 原生 User 模組的 authenticate()
,所以換個方法,不是修改 TokenObtainPairSerializer
中的 validate()
,而是嘗試改變 Django提供的 authentication 介面,讓使用 email 與 password 的驗證方法得以實現。
這個方式是非常快速且簡易的方法,使用這種方法,不論使用者輸入的是 username 還是 email,後端都可以在接收到資料後成功進行驗證並回傳 JWT token。
分享就到這邊,如果喜歡我的文章可以幫我拍個幾下手,在閱讀文章時如果有遇到什麼問題,或是有什麼建議,都歡迎留言告訴我,謝謝。 😃