Evgenii Legotckoi
Evgenii Legotckoi14. Februar 2022 04:24

Django Rest Framework – Tutorial 001. Token-Authentifizierung hinzufügen

Im Moment arbeite ich aktiv an einer Anwendung, die mit der REST-API einer Django-Site funktioniert. Und einer der ersten Schritte bestand darin, die Benutzerauthentifizierung per Token einzurichten, aber damit dies funktioniert, müssen Sie zuerst ein Autorisierungstoken erhalten.

Schauen wir uns an, wie dies geschehen kann.


Django Rest Framework installieren

Da dies der allererste Artikel zur Verwendung von DRF ist, werde ich den Prozess der Installation und Konfiguration von DRF ausführlicher beschreiben. Im Folgenden werde ich diese Anweisungen nicht mehr geben.

Installieren Sie DRF und andere erforderliche Pakete

pip install djangorestframework
pip install markdown       # Markdown support for the browsable API.
pip install django-filter

Fügen Sie als Nächstes die Anwendung „rest_frameword“ zu INSTALLED_APPS in der Site-Konfigurationsdatei settings.py hinzu

INSTALLED_APPS = [
    ...
    'rest_framework',
]

Darüber hinaus schlägt die offizielle Dokumentation vor, die Login- und Logout-Ansicht von rest_framework in die Datei urls.py aufzunehmen, damit Sie die API bequem im Browser verwenden können.

Um ehrlich zu sein, verwende ich diese API nicht, weil es für mich bequemer ist, die durch Swagger generierte Dokumentation zu verwenden, auf die ich später noch zu sprechen komme, aber ich verbinde trotzdem die View-Daten, damit ich keine zufälligen Probleme löse später.

urlpatterns = [
    ...
    path('api-auth/', include('rest_framework.urls')),
]

Konfigurieren Sie als Nächstes die Standardauthentifizierung und die Berechtigungsklassen (auch in settingsp.py).

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

Jetzt ist alles bereit, um einen Zugangspunkt zu schreiben, um einen Token zu erhalten. Aber zuerst möchte ich die Generierung der Swagger-Dokumentation anschließen. Es ist einfach bequemer so zu arbeiten, mir gefällt zum Beispiel die redoc-Dokumentation sehr gut, in der alles recht schön und übersichtlich dargestellt wird.

Swagger installieren

Und jetzt werden wir Swagger sofort auf der Website verbinden. Ich verstehe, dass dies nicht mit dem Thema des Artikels zusammenhängt, aber im Code mache ich spezielle Manipulationen, um eine spezielle Dokumentationsanzeige zu ermöglichen, und ich denke, dass dies in Zukunft für Sie nützlich sein kann, weil:

  • Sie werden in Zukunft Swagger verwenden
  • Manchmal müssen Sie die Ausgabe von Informationen in der API-Beschreibung anpassen, nämlich für das Token hatte ich die spezifischste Änderung für Swagger.

Установим drf-yasg

Führen Sie dazu gemäß der Dokumentation den folgenden Befehl aus

pip install -U drf-yasg

Dann ändern wir die Datei settings.py

INSTALLED_APPS = [
   ...
   'django.contrib.staticfiles',  # required for serving swagger ui's css/js files
   'drf_yasg',
   ...
]

Und jetzt registrieren wir Swagger in den Site-URLs

from django.urls import re_path
from drf_yasg import openapi
from drf_yasg.views import get_schema_view
from rest_framework import permissions

schema_view = get_schema_view(
   openapi.Info(
      title="EXAMPLE API",
      default_version='v1',
      description="REST API Documentation",
      contact=openapi.Contact(email="example@example.com"),
   ),
   public=True,
   permission_classes=(permissions.IsAdminUser,),
)

urlpatterns = [
    ...
    re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
    re_path(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
    re_path(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]

Wenn Sie sich den Code genau ansehen, werden Sie feststellen, dass ich den Swagger nur für die Verwaltung der Website registriert habe. Wenn Sie möchten, dass die Dokumentation geöffnet ist, entfernen Sie diese Zeile

permission_classes=(permissions.IsAdminUser,),

Optional können Sie der Dokumentationsausgabe Informationen darüber hinzufügen, welche Authentifizierungstypen für die API verwendet werden. Dies geschieht in der Datei settings.py.

SWAGGER_SETTINGS = {
   'SECURITY_DEFINITIONS': {
      'Basic': {
            'type': 'basic'
      },
      'Bearer': {
            'type': 'apiKey',
            'name': 'Authorization',
            'in': 'header'
      }
   }
}

Jetzt können Sie mit der Implementierung eines Zugriffspunkts beginnen, um ein Token zu erhalten.

API-Anwendung

Lassen Sie uns eine API-Anwendung erstellen, in der ein Endpunkt hinzugefügt wird, um ein Token zu erhalten.

python manage.py startapp api

serializers.py

Als Nächstes erstellen wir eine Datei mit Serializern, in der ein spezieller Serializer erstellt wird, der die Antwort der Site in Swagger beschreibt.

# -*- coding: utf-8 -*-

from rest_framework import serializers


class Response201AuthTokenSerializer(serializers.Serializer):
    token = serializers.CharField(required=True, allow_blank=False)
    user_id = serializers.IntegerField(required=True)

Dieser Serializer generiert die Antwortinformationen in der Dokumentation korrekt und ich verwende ihn, um eine JSON-Antwort mit einem Token zu generieren.

views.py

Dann ändern wir die Datei views.py, um den Endpunkt zu erhalten.

# -*- coding: utf-8 -*-

from django.contrib.auth import get_user_model
from django.http import JsonResponse
from django.utils.translation import gettext_lazy as _
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import authentication, viewsets
from rest_framework.authtoken.views import ObtainAuthToken

from api.serializers import Response201AuthTokenSerializer


class CustomAuthToken(ObtainAuthToken):
    authentication_classes = [authentication.BasicAuthentication]

    @swagger_auto_schema(responses={
        "201": openapi.Response(
            description=_("User has got Token"),
            schema=Response201AuthTokenSerializer,
        )
    })
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                           context={'request': request})
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
        response201 = Response201AuthTokenSerializer(data={"token": token.key, "user_id": user.pk})
        response201.is_valid(raise_exception=True)
        return JsonResponse(response201.data)

Wie Sie im Code sehen können, gibt es ein benutzerdefiniertes Swagger-Schema für die 201-Antwort, der Inhalt wurde erstellt. Die korrekte Dokumentation wird vom Response201AuthTokenSerializer-Serializer generiert.
Unter anderem verwende ich den Response201AuthTokenSerializer, um eine Antwort mit einem Token sowie einer Benutzer-ID zu bilden. In Zukunft verwende ich die Benutzer-ID, um Daten in einer mobilen Anwendung zu manipulieren.
Eine Besonderheit dieser Ansicht ist, dass nur BasicAuthentication als Authentifizierung verwendet wird, dh der Benutzer erhält Zugriff auf diese Ansicht nur über Benutzername und Passwort. In Zukunft ist die API-Entwicklung im Gange, um das Token zu verwenden.

urls.py

Und jetzt verbinden Sie die Ansicht, um das Token in den URL-Dateien zu erhalten

# -*- coding: utf-8 -*-

from django.urls import path

from api import views


app_name = 'api'
urlpatterns = [
    path('api-token-auth/', views.CustomAuthToken.as_view()),
]

In dieser Datei definieren wir den Namen der Anwendung, die zum Generieren von Routen verwendet wird, also api. Wir verbinden auch die Ansicht des Tokens mit dem Routing.

Und am Ende fügen wir die urls.py der API-Anwendung in die Hauptdatei urls.py des gesamten Projekts ein.

urlpatterns = [
    ...
    path('api/', include('api.urls')),
    ...
]

Um nun ein Token zu erhalten, müssen Sie eine POST-Anfrage an die URL http://127.0.0.1/api/api-token-auth/ senden, wenn Sie die Funktionalität auf einem lokalen testen möchten Server. Im Falle eines Kampfservers müssen Sie eine Anfrage an die Adresse mit der Domain Ihrer Website senden.

Für die Authentifizierung müssen Sie die Standardauthentifizierung verwenden.

Beispiel einer Token-Anfrage in Felgo QML

Hier ist ein Beispielcode zum Anfordern eines Tokens in einer in QML Felgo geschriebenen Anwendung

function login(username, password, success, error) {
    HttpRequest
    .post("http://127.0.0.1/api/api-token-auth/", {username: username, password: password})
    .timeout(5000)
    .set('Content-Type', 'application/json')
    .then(function(res) { success(res) })
    .catch(function(err) { error(err) });
}
Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

BL4CK R4BBIT
  • 14. Februar 2022 06:42

Доброго времени.
А если кастомный юзер.
И активация юзера подтверждением по смс или звонку?

Evgenii Legotckoi
  • 14. Februar 2022 06:54
  • (bearbeitet)

Добрый день

Если Вы имеетe ввиду, что модель пользователя наследована от AbstractUser и переопределена для проекта, то да - этот пример рабочий, я сейчас занимаюсь одним проектом, который будет иметь приложение и использую там кастомного пользователя.

А что касается подтверждения по СМС, то я участвовал несколько лет назад в проекте, где было подтверждение по СМС. Код показать не могу, но суть была в том, что там было два REST API View, сначало приложение стучалось на первый url, куда посылало логин и пароль, при получении ответа 200, приложение меняло форму ввода данных и ждало, пока пользователь заполнит код из СМС и подтвердит отправку. В этом случае отправка кода была уже на второй url, который проверял правильность кода, и уже в этом случае отдавал токен.

Естественно первый URL, который обрабатывал логин и пароль, стучался на API стороннего провайдера по отправке СМС, получал отправленный код и сохранял в отдельную таблицу, чтобы потом сравнить код и соответствие пользователя коду.

BL4CK R4BBIT
  • 14. Februar 2022 07:14
  • (bearbeitet)

В моем случае кастом от AbstractBaseUser

class User(AbstractBaseUser):
    phone       = PhoneNumberField(region='RU', unique=True)
    username    = models.CharField(max_length = 150, blank = True, null = True)
    standard    = models.CharField(max_length = 3, blank = True, null = True)
    score       = models.IntegerField(default = 16)
    first_login = models.BooleanField(default=False)
    active      = models.BooleanField(default=False)
    staff       = models.BooleanField(default=False)
    admin       = models.BooleanField(default=False)
    timestamp   = models.DateTimeField(auto_now_add=True)

    USERNAME_FIELD = 'phone'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def __str__(self):
        return self.phone

    def get_full_name(self):
        return self.phone

    def get_short_name(self):
        return self.phone

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):

        return True

    @property
    def is_staff(self):
        return self.staff

    @property
    def is_admin(self):
        return self.admin

    @property
    def is_active(self):
        return self.active

Только токен я использую knox(Стандарт мобильной безопастности Samsung), потому и спросил

Дальше понятно:
Регистрация post на страницу урл api/register(можно сразу отправить запрос на звонок, после создания пользователя)
Если удачно то получим 4-x символьный код от провайдера, запищем его. Если неудачно то создаем свой и шлем смс
Cледом post-запрос на верификацию с кодом(при удаче - активируем пользователя, при не удаче 4 попытки на повтор)

Evgenii Legotckoi
  • 14. Februar 2022 07:22

В таком случае без напильника этот код сходу не взлетит, если конкретно knox нужно использовать.
А касательно самого AbstractBaseUser, то должно заработать.

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 10:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken