api 存储在 api_credentials table 中的 Django 休息框架基本身份验证

Django rest framework basic auth for api store in api_credentials table

我想对 api 使用 Basic Auth,它接收 JSON 数据并存储在数据库 table 中。我遇到的问题是为 API 设置 Basic Auth。 API 用户名和密码存储在 api_credentials table 2 个单独的列中。与用户table.

无关

在我的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 是我的授权 class。我怎样才能在那个 class 中写我的验证码。或者还有其他更好的方法吗?

好吧,根据 documentation,您不能使用 authentication_classes,因为您与具有凭据的用户模型没有任何关系。而且你也不能使用权限 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_tableUser 模型之间有关系,那么您可以像这样覆盖 BasicAuthetication class:

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中使用它。希望对您有所帮助!!