在本教程中,您將學習如何使用Django REST框架(DRF)實現基於標記的身份驗證。令牌身份驗證的工作方式是將用戶名和密碼交換爲令牌,以便在所有後續請求中使用該令牌來標識服務器端的用戶。
1. 設置項目
讓我們從頭開始。安裝Django和DRF:
pip install django
pip install djangorestframework
新建一個項目
django-admin.py startproject myapi .
進入項目目錄
cd myapi
啓動一個新的應用程序,命名爲core:
django-admin.py startapp core
你的項目結構應該是這樣的:
myapi/
|-- core/
| |-- migrations/
| |-- __init__.py
| |-- admin.py
| |-- apps.py
| |-- models.py
| |-- tests.py
| +-- views.py
|-- __init__.py
|-- settings.py
|-- urls.py
+-- wsgi.py
manage.py
在settings.py模塊中,將您創建的應用程序core
和安裝的rest_framework
應用程序添加到INSTALLED_APPS
:
myapi/settings.py
INSTALLED_APPS = [
# Django Apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third-Party Apps
'rest_framework',
# Local Apps (Your project's apps)
'myapi.core',
]
返回項目根目錄(manage.py
腳本所在的文件夾),遷移數據庫:
python manage.py migrate
讓我們創建我們的第一個API視圖來測試一下:
myapi/core/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
class HelloView(APIView):
def get(self, request):
content = {'message': 'Hello, World!'}
return Response(content)
現在在url .py
模塊中註冊一個路徑:
myapi/urls.py
from django.urls import path
from myapi.core import views
urlpatterns = [
path('hello/', views.HelloView.as_view(), name='hello'),
]
現在我們有了一個/hello/
的API,我們可以執行GET請求。我們可以使用瀏覽器來使用這個端點,只需訪問URL http://127.0.0.1:8000/hello/
我們還可以通過傳遞querystring
中的格式參數(如http://127.0.0.1:8000/hello/?format= JSON
)來請求接收作爲普通JSON數據的響應:
這兩種方法都適合嘗試DRF API,但有時命令行工具更方便,因爲我們可以更輕鬆地處理請求頭。您可以使用curl
,它在所有主要的Linux/macOS發行版上都廣泛可用
curl http://127.0.0.1:8000/hello/
但通常我更喜歡使用HTTPie,這是一個非常棒的Python命令行工具:
http http://127.0.0.1:8000/hello/
現在我們使用token
來保護這個API端點,這樣我們就可以實現基於token
的身份驗證:
myapi/core/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated # <-- Here
class HelloView(APIView):
permission_classes = (IsAuthenticated,) # <-- And here
def get(self, request):
content = {'message': 'Hello, World!'}
return Response(content)
再次嘗試訪問API接口
http http://127.0.0.1:8000/hello/
現在我們得到一個HTTP 403禁止錯誤。現在讓我們實現令牌身份驗證,以便訪問此端點。
2. 實現令牌身份驗證
我們需要在settings.py
模塊中添加兩條信息。第一個包括rest_framework.authtoken
到你的INSTALLED_APPS
,幷包含到REST_FRAMEWORK
的TokenAuthentication
:
myapi/settings.py
INSTALLED_APPS = [
# Django Apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third-Party Apps
'rest_framework',
'rest_framework.authtoken', # <-- Here
# Local Apps (Your project's apps)
'myapi.core',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # <-- And here
],
}
遷移數據庫以創建表來存儲身份驗證令牌
python manage.py migrate
現在我們需要一個用戶帳戶,讓我們創建一個使用manage.py
命令行實用工具:
python manage.py createsuperuser --username vitor --email vitor@example.com
生成令牌的最簡單方法(僅用於測試
)是再次使用命令行實用工具:
python manage.py drf_create_token vitor
這段信息,隨機字符串9054f7aa9305e012b3c2300408c3dfdf390fcddf
是我們接下來要使用的身份驗證
現在我們有了TokenAuthentication
請求認證,讓我們嘗試向/hello/
接口再次發出一個請求
http http://127.0.0.1:8000/hello/
注意我們的API現在向客戶端提供請求信息是需要認證方法的。
最後,讓我們使用我們的token!
http http://127.0.0.1:8000/hello/ 'Authorization: Token 9054f7aa9305e012b3c2300408c3dfdf390fcddf'
差不多就是這樣。現在,對於所有後續請求,您應該包括頭部授權:Token 9054f7aa9305e012b3c2300408c3dfdf390fcddf
格式看起來很奇怪,通常在如何設置這個標題上很容易混淆。這將取決於客戶端如何設置HTTP請求頭。
如,如果我們使用curl
,命令應該是這樣的:
curl http://127.0.0.1:8000/hello/ -H 'Authorization: Token 9054f7aa9305e012b3c2300408c3dfdf390fcddf'
或者如果是python requests
調用:
import requests
url = 'http://127.0.0.1:8000/hello/'
headers = {'Authorization': 'Token 9054f7aa9305e012b3c2300408c3dfdf390fcddf'}
r = requests.get(url, headers=headers)
用戶獲取Token
DRF
爲用戶提供一個接口,以便使用用戶名和密碼請求身份驗證令牌,包括以下路由到urls.py模塊
myapi/urls.py
from django.urls import path
from rest_framework.authtoken.views import obtain_auth_token # <-- Here
from myapi.core import views
urlpatterns = [
path('hello/', views.HelloView.as_view(), name='hello'),
path('api-token-auth/', obtain_auth_token, name='api_token_auth'), # <-- And here
]
現在我們有了一個全新的API接口,它是/api-token-auth/
,讓我們先來看看
http http://127.0.0.1:8000/api-token-auth/
它不處理GET請求。基本上它只是一個接收帶有username
和password
的POST請求的視圖。
http post http://127.0.0.1:8000/api-token-auth/ username=vitor password=123
響應體是與此特定用戶關聯的令牌,在此之後,您將存儲此令牌並將其應用於未來的請求中。
如果這是一個Angular
客戶端,你可以把令牌存儲在localStorage
中,如果這是一個桌面CLI
應用程序,你可以把它存儲在一個點文件
中(即隱藏文件),放在用戶主目錄的一個文本文件中。
總結
需要注意的是,默認的令牌實現有一些限制,比如每個用戶只有一個令牌,沒有爲令牌設置過期日期的內置方法。