Python DRF中受身份验证保护的基本视图
我有一些API端点需要在Django Rest框架中使用HTTP基本身份验证进行保护。DRF中有,但这实际上是针对Django中的用户进行身份验证,这不是我要寻找的 我找到了一个使用自定义权限的解决方案,但ti意味着对视图进行修补以设置正确的authenticate标头 有更好的办法吗Python DRF中受身份验证保护的基本视图,python,django,django-rest-framework,Python,Django,Django Rest Framework,我有一些API端点需要在Django Rest框架中使用HTTP基本身份验证进行保护。DRF中有,但这实际上是针对Django中的用户进行身份验证,这不是我要寻找的 我找到了一个使用自定义权限的解决方案,但ti意味着对视图进行修补以设置正确的authenticate标头 有更好的办法吗 class BasicAuthPermission(permissions.BasePermission): def has_permission(self, request, view):
class BasicAuthPermission(permissions.BasePermission):
def has_permission(self, request, view):
credentials = view.credentials # Will raise AttributeError on missing credentials
realm = getattr(view, 'realm', 'Protected')
auth = request.headers.get('Authorization')
with suppress(ValueError, AttributeError):
auth = b64decode(auth.split()[-1]).decode()
if auth != credentials:
# Monkey patch style
view.get_authenticate_header = lambda r: f'Basic realm="{realm}"'
raise exceptions.AuthenticationFailed('Bad credentials.')
return True
我的看法是:
class ProtectedApiView(generics.GenericAPIView):
permission_classes = [BasicAuthPermission]
credentials = 'user:password'
# ...
按照Arakkal在评论中的建议,我改为使用身份验证类。它确实感觉不那么粗糙,但我不能像最初那样在视图上设置凭据 我意识到“匿名身份验证”是个奇怪的名字,但那是因为Django对用户一无所知。因此,出于所有实际目的,匿名
from base64 import b64decode
import binascii
from rest_framework import generics, exceptions, authentication
class AnonymousBasicAuthentication(authentication.BaseAuthentication):
"""
HTTP Basic authentication against preset credentials.
"""
www_authenticate_realm = 'api'
credentials: str = None
def authenticate(self, request):
try:
auth, encoded = authentication.get_authorization_header(request).split(maxsplit=1)
except ValueError:
raise exceptions.AuthenticationFailed('Invalid basic header.')
if not auth or auth.lower() != b'basic':
raise exceptions.AuthenticationFailed('Authentication needed')
try:
credentials = b64decode(encoded).decode(authentication.HTTP_HEADER_ENCODING)
except (TypeError, UnicodeDecodeError, binascii.Error):
raise exceptions.AuthenticationFailed('Invalid basic header. Credentials not correctly base64 encoded.')
if self.credentials != credentials:
raise exceptions.AuthenticationFailed('Invalid username/password.')
def authenticate_header(self, request):
return 'Basic realm="{}"'.format(self.www_authenticate_realm)
class MyAuthentication(AnonymousBasicAuthentication):
credentials = 'user:password'
class MyProtectedView(generics.GenericAPIView):
authentication_classes = [MyAuthentication]
# ...
用户和用户名:密码之间没有任何关系?我认为这应该是一个身份验证过程,而不是授权过程。在真正的代码中,我把凭证放在一个设置文件中,但为了清晰起见,我把字符串放在这里。因此,我想我应该编写一个自定义的身份验证类,这种不用于标识用户的身份验证应该留在web服务器上(nginx、apache等等),并保留在Django之外