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_table
和 User
模型之间有关系,那么您可以像这样覆盖 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
中使用它。希望对您有所帮助!!
我想对 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_table
和 User
模型之间有关系,那么您可以像这样覆盖 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
中使用它。希望对您有所帮助!!