Evgenii Legotckoi
Evgenii LegotckoiАқп. 14, 2022, 4:24 Т.Ж.

Django Rest Framework - Оқулық 001. Токен аутентификациясын қосу

Қазіргі уақытта мен Django сайтының REST API интерфейсімен жұмыс істейтін қолданбада белсенді жұмыс істеп жатырмын. Алғашқы қадамдардың бірі пайдаланушы аутентификациясын токен арқылы орнату болды, бірақ бұл жұмыс істеуі үшін алдымен авторизация белгісін алу керек.

Мұны қалай жасауға болатынын қарастырайық.


Django Rest Framework орнату

Бұл DRF пайдалану туралы ең бірінші мақала болғандықтан, мен DRF орнату және конфигурациялау процесін толығырақ сипаттайтын боламын. Бұдан әрі мен бұл нұсқауларды бермеймін.

DRF және басқа қажетті бумаларды орнатыңыз

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

Әрі қарай, settings.py сайт конфигурация файлындағы INSTALLED_APPS қолданбасына "rest_frameword" қолданбасын қосыңыз.

INSTALLED_APPS = [
    ...
    'rest_framework',
]

Бұдан басқа, ресми құжаттама urls.py файлында rest_framework ішінен кіру және шығу көрінісін қосуды ұсынады, осылайша браузерде API интерфейсін ыңғайлы пайдалана аласыз.

Шынымды айтсам, мен бұл API қолданбаймын, өйткені мен үшін сваггер арқылы жасалған құжаттаманы пайдалану ыңғайлы, ол туралы кейінірек айтатын боламын, бірақ мен кездейсоқ мәселелерді шешпеу үшін View деректерін қосамын. кейінірек.

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

Содан кейін әдепкі аутентификация және рұқсат сыныптарын конфигурациялаңыз (сонымен қатар 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',
    ],
}

Енді токенді алу үшін кіру нүктесін жазу үшін бәрі дайын. Бірақ алдымен мен генерацияланатын құжаттаманы байланыстырғым келеді. Бұл әдіспен жұмыс істеу ыңғайлырақ, мысалы, маған бәрі өте әдемі және ыңғайлы түрде көрсетілетін redoc құжаттамасы өте ұнайды.

Swagger орнатылуда

Енді біз сайтқа свагерді бірден қосамыз. Мен бұл мақаланың тақырыбына қатысты емес екенін түсінемін, бірақ кодта мен арнайы құжаттаманы көрсетуді қосу үшін арнайы манипуляциялар жасаймын және бұл болашақта сізге пайдалы болуы мүмкін деп ойлаймын, себебі:

  • Болашақта свеггерді қолданасыз
  • Кейде API сипаттамасындағы ақпараттың шығысын теңшеу қажет болады, атап айтқанда, менде сваггер үшін ең ерекше өзгеріс болған таңбалауыш үшін.

Мен drf-yasg орнатамын

Ол үшін құжаттамадан кейін келесі пәрменді іске қосыңыз

pip install -U drf-yasg

Содан кейін settings.py файлын өзгертеміз

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

Ал енді свагерді сайттың URL мекенжайларына тіркейік

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'),
]

Кодты мұқият қарап шықсаңыз, мен свеггерді тек сайт әкімшілігі үшін тіркегенімді көресіз. Құжаттаманың ашық болуын қаласаңыз, осы жолды алып тастаңыз

permission_classes=(permissions.IsAdminUser,),

Қосымша түрде құжаттаманың шығысына API үшін қандай аутентификация түрлері пайдаланылатыны туралы ақпаратты қосуға болады. Бұл settings.py файлында орындалады.

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

Енді таңбалауышты алу үшін кіру нүктесін енгізуді бастауға болады.

Қолданбаның API

Токенді қабылдау үшін соңғы нүкте қосылатын api қолданбасын жасайық.

python manage.py startapp api

serializers.py

Әрі қарай, біз сериализаторлары бар файлды жасаймыз, онда арнайы сериализатор жасалатын болады, ол сайттың жауабын сваггерде сипаттайды.

# -*- 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)

Бұл сериализатор құжаттамадағы жауап ақпаратын дұрыс жасайды және мен оны таңбалауышпен JSON жауабын жасау үшін қолданамын.

views.py

Содан кейін соңғы нүктені алу үшін views.py файлын өзгертеміз.

# -*- 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)

Кодта көріп отырғаныңыздай, 201 жауабы үшін теңшелетін свеггер схемасы бар, мазмұн жасалды. Дұрыс құжаттама Response201AuthTokenSerializer сериализаторынан жасалады.
Басқа нәрселермен қатар мен Response201AuthTokenSerializer қолданбасын таңбалауышпен, сондай-ақ пайдаланушы идентификаторымен жауап қалыптастыру үшін пайдаланамын. Болашақта мен мобильді қосымшадағы деректерді өңдеу үшін пайдаланушы идентификаторын қолданамын.
Бұл көріністің ерекше нюансы түпнұсқалық растама ретінде тек BasicAuthentication пайдаланылады, яғни пайдаланушы бұл көрініске тек пайдаланушы аты мен құпия сөз арқылы қол жеткізе алады. Болашақта токенді пайдалану үшін API әзірленуде.

urls.py

Енді URL файлдарындағы таңбалауышты алу үшін көріністі қосыңыз

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

from django.urls import path

from api import views


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

Бұл файлда біз маршруттарды жасау үшін қолданылатын қолданбаның атын анықтаймыз, яғни api. Маршрутизацияға маркердің көрінісін де қосамыз.

Соңында біз бүкіл жобаның негізгі urls.py файлына api қолданбасының urls.py файлын қосамыз.

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

Енді токенді алу үшін http://127.0.0.1/api/api-token-auth/ url мекенжайына POST сұрауын жіберу керек, егер сіз жергілікті жерде функционалдылықты сынағыңыз келсе сервер. Жауынгерлік сервер жағдайында сіз өзіңіздің сайтыңыздың доменімен мекенжайға сұрау жіберуіңіз керек.

Аутентификация үшін негізгі аутентификацияны пайдалану қажет.

Felgo QML жүйесіндегі таңбалауыш сұрауының мысалы

Мұнда QML Felgo тілінде жазылған қолданбада таңбалауышты сұрауға арналған мысал коды берілген

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
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

BL4CK R4BBIT
  • Ақп. 14, 2022, 6:42 Т.Ж.

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

Evgenii Legotckoi
  • Ақп. 14, 2022, 6:54 Т.Ж.
  • (өңделген)

Добрый день

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

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

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

BL4CK R4BBIT
  • Ақп. 14, 2022, 7:14 Т.Ж.
  • (өңделген)

В моем случае кастом от 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, 2022, 7:22 Т.Ж.

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

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз