[英]Basic auth protected views in DRF
我有一些 API 端點,我需要使用 Django Z55276C10D84E1DF74E71B3 中的 HTTP 基本身份驗證來保護這些端點。 DRF 中有BasicAuthentication ,但實際上對 Django 中的用戶進行身份驗證,這不是我想要的。
我找到了使用自定義權限的解決方案,但 ti 意味着猴子修補視圖以設置正確的身份驗證 header。
有沒有更好的辦法?
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 在評論中的建議,我使用 Authentication class 來代替。 它確實感覺不那么hacky,但我不能像我最初那樣在視圖上設置憑據。
我意識到“匿名身份驗證”是一個奇怪的名稱,但那是因為 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]
# ...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.