Как реализовать аутентификацию по токену с помощью Django REST Framework
В этом руководстве вы узнаете, как реализовать аутентификацию на основе токенов с помощью Django REST Framework (DRF). Аутентификация на основе токенов работает путем обмена имени пользователя и пароля на токен, который будет использоваться во всех последующих запросах для идентификации пользователя на стороне сервера.
Специфика обработки аутентификации на стороне клиента зависит от технологии/языка/фреймворка, с которым вы работаете. Клиент может быть мобильным приложением, использующим iOS или Android. Это может быть настольное приложение с использованием Python или C++. Это может быть веб-приложение на PHP или Ruby.
Но как только вы поймете общий процесс, вам будет легче найти необходимые ресурсы и документацию для вашего конкретного случая использования.
Аутентификация по токену подходит для клиент-серверных приложений, где токен безопасно хранится. Вы никогда не должны раскрывать свой токен, так как это (в некотором роде) эквивалентно передаче своего имени пользователя и пароля.
Оглавление
- Установка проекта REST API (Если вы уже знаете, как начать проект DRF, вы можете пропустить это)
- Внедрение аутентификации по токену
- Пользователь, запрашивающий токен
- Выводы
Установка проекта REST API
Итак, давайте начнем с самого начала. Установите Django и DRF:
pip install django
pip install djangorestframework
Создайте новый проект Django:
django-admin.py startproject myapi .
Перейдите в папку 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
Добавьте приложение core (которое вы создали) и приложение rest_framework (которое вы установили) в INSTALLED_APPS
, внутри модуля settings.py:
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)
Теперь зарегистрируйте путь в модуле urls.py:
myapi/urls.py
from django.urls import path
from myapi.core import views
urlpatterns = [
path('hello/', views.HelloView.as_view(), name='hello'),
]
Итак, теперь у нас есть API с одной конечной точкой /hello/
, к которой мы можем выполнять GET
запросы. Мы можем использовать браузер для потребления этой конечной точки, просто обратившись к URL http://127.0.0.1:8000/hello/
:
Мы также можем попросить получить ответ в виде простых данных JSON, передав параметр format
в строке запроса, как http://127.0.0.1:8000/hello/?format=json
:
Оба метода подходят для опробования DRF API, но иногда инструмент командной строки более удобен, так как мы можем легче играть с заголовками запросов. Вы можете использовать cURL, который широко доступен во всех основных дистрибутивах Linux/macOS:
curl http://127.0.0.1:8000/hello/
Но обычно я предпочитаю использовать HTTPie, который является довольно удивительным инструментом командной строки Python:
http http://127.0.0.1:8000/hello/
Теперь давайте защитим эту конечную точку API, чтобы мы могли реализовать аутентификацию с помощью токенов:
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 Forbidden. Теперь давайте реализуем аутентификацию токена, чтобы мы могли получить доступ к этой конечной точке.
Внедрение аутентификации по токену
Нам нужно добавить две части информации в наш модуль settings.py. Сначала включите rest_framework.authtoken в ваш INSTALLED_APPS
и включите TokenAuthentication
в REST_FRAMEWORK
:
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 теперь предоставляет клиенту дополнительную информацию о требуемом методе аутентификации.
Наконец, давайте используем наш токен!
http http://127.0.0.1:8000/hello/ 'Authorization: Token 9054f7aa9305e012b3c2300408c3dfdf390fcddf'
И это практически все. Впредь во всех последующих запросах вы должны включать заголовок Authorization: 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)
Однако, если бы мы использовали Angular, вы могли бы реализовать HttpInterceptor
и установить заголовок:
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const user = JSON.parse(localStorage.getItem('user'));
if (user && user.token) {
request = request.clone({
setHeaders: {
Authorization: `Token ${user.accessToken}`
}
});
}
return next.handle(request);
}
}
Пользователь запрашивает токен
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-запросы. По сути это просто представление для получения POST запроса с именем пользователя и паролем.
Попробуем еще раз:
http post http://127.0.0.1:8000/api-token-auth/ username=vitor password=123
В теле ответа находится токен, связанный с этим конкретным пользователем. После этого момента вы храните этот токен и применяете его к будущим запросам.
Тогда, опять же, способ выполнения POST-запроса к API зависит от используемого языка/фреймворка.
Если бы это был клиент Angular, вы могли бы хранить токен в localStorage
, если бы это было приложение Desktop CLI, вы могли бы хранить в текстовом файле в домашнем каталоге пользователя в файле dot.
Выводы
Надеемся, что это руководство дало некоторое представление о том, как работает аутентификация с помощью токенов. Я постараюсь продолжить это руководство, предоставив несколько конкретных примеров приложений Angular, приложений командной строки и веб-клиентов.
Важно отметить, что реализация Token по умолчанию имеет некоторые ограничения, такие как только один токен на пользователя, нет встроенного способа установить дату истечения срока действия токена.
Вернуться на верх