在本教程中,您将学习如何使用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
应用程序,你可以把它存储在一个点文件
中(即隐藏文件),放在用户主目录的一个文本文件中。
总结
需要注意的是,默认的令牌实现有一些限制,比如每个用户只有一个令牌,没有为令牌设置过期日期的内置方法。