Базовая аутентификация фреймворка Django для API-магазина в таблице api_credentials - PullRequest
0 голосов
/ 25 ноября 2018

Я хочу использовать Basic Auth для API, который получает данные JSON и сохраняет их в таблице базы данных.Проблема, с которой я столкнулся, заключается в настройке Basic Auth для API.Имя пользователя и пароль API хранятся в таблице api_credentials в 2 отдельных столбцах.Это не имеет никакого отношения к пользовательской таблице.

В моем api.py

class EventDataViewSet(mixins.CreateModelMixin,
                         mixins.ListModelMixin,
                         viewsets.GenericViewSet):
    queryset = models.EventData.objects.all()
    serializer_class = serializers.EventDataSerializer
    authentication_classes = (eventdataapiauth,) # I write this class
    permission_classes = (permissions.IsAuthenticated,)

eventdataapiauth - мой класс аутентификации.Как я могу написать свой код аутентификации в этом классе.Или есть другой лучший способ сделать это?

1 Ответ

0 голосов
/ 25 ноября 2018

Ну, согласно документации , вы не можете использовать authentication_classes, потому что вы не имеете никакого отношения к модели пользователя с учетными данными.И вы также не можете использовать классы разрешений, потому что permissions.isAuthenticated проверяет, есть ли в запросе какой-либо пользовательский экземпляр и проверен ли он, как if request.user.is_authenticated.

Так что вы можете использовать этот подход вместо декоратора.Попробуйте так:

import binascii
import base64
from django.utils.translation import ugettext_lazy as _
from rest_framework import status
from rest_framework.authentication import get_authorization_header
from rest_framework import HTTP_HEADER_ENCODING



def check_authenticated(function):
    def wrapper(obj, request, *args, **kw):
        auth = get_authorization_header(request).split()
        if not auth or auth[0].lower() != b'basic':
            msg = _("Not basic authentication.")
            return Response(data={'error': msg}, status=status.HTTP_401_UNAUTHORIZED)

        if len(auth) == 1:
            msg = _('Invalid basic header. No credentials provided.')
            return Response(data={'error': msg}, status=status.HTTP_401_UNAUTHORIZED)
        elif len(auth) > 2:
            msg = _('Invalid basic header. Credentials string should not contain spaces.')
            return Response(data={'error': msg}, status=status.HTTP_401_UNAUTHORIZED)

        try:
            auth_parts = base64.b64decode(auth[1]).decode(HTTP_HEADER_ENCODING).partition(':')
        except (TypeError, UnicodeDecodeError, binascii.Error):
            msg = _('Invalid basic header. Credentials not correctly base64 encoded.')
            return Response(data={'error': msg}, status=status.HTTP_401_UNAUTHORIZED)

        userid, password = auth_parts[0], auth_parts[2]
        # Your auth table specific codes
        if AuthTable.objects.filter(username=userid, password=password).exists():  # my dummy code
            return function(obj, request, *args, **kw)
        else:
            msg = _('User not found.')
            return Response(data={'error': msg}, status=status.HTTP_401_UNAUTHORIZED)
    return wrapper

Теперь используйте это в своем ViewSet следующим образом:

class EventDataViewSet(mixins.CreateModelMixin,
                         mixins.ListModelMixin,
                         viewsets.GenericViewSet):
     queryset = models.EventData.objects.all()
     serializer_class = serializers.EventDataSerializer
     authentication_classes = []
     permission_classes = []

     @check_authenticated
     def create(self, request, *args, **kwargs):
          return super(EventDataViewSet, self).create(request,*args, **kwargs)

     @check_authenticated
     def list(self, request, *args, **kwargs):
          return super(EventDataViewSet, self).list(request,*args, **kwargs)

Но если у вас есть связь между auth_table и User моделью, то вы можетепереопределить BasicAuthetication класс следующим образом:

class EventDataApiAuth(BasicAuthentication):

    def authenticate_credentials(self, userid, password, request=None):
        user = AuthData.objects.get(username=userid, password=password).user  # assuming auth_table has a ForeignKey relation to User
        return (user, None)

и использовать его в authentication_classes.Надеюсь, это поможет !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...