feat: harden phase 3 api security
This commit is contained in:
@@ -5,6 +5,7 @@ from rest_framework.authentication import BaseAuthentication, get_authorization_
|
||||
from rest_framework.exceptions import AuthenticationFailed, PermissionDenied
|
||||
|
||||
from apps.api.errors import api_error
|
||||
from apps.api.throttles import throttle_api_auth_failure
|
||||
from apps.users.models import ApiKey
|
||||
|
||||
|
||||
@@ -19,24 +20,24 @@ class ApiKeyAuthentication(BaseAuthentication):
|
||||
try:
|
||||
header = raw_header.decode("utf-8")
|
||||
except UnicodeError as exc:
|
||||
raise self.authentication_failed() from exc
|
||||
raise self.authentication_failed(request) from exc
|
||||
|
||||
parts = header.split()
|
||||
if len(parts) != 2 or parts[0].lower() != self.keyword.lower():
|
||||
raise self.authentication_failed()
|
||||
raise self.authentication_failed(request)
|
||||
|
||||
raw_key = parts[1]
|
||||
if not raw_key:
|
||||
raise self.authentication_failed()
|
||||
raise self.authentication_failed(request)
|
||||
|
||||
key_hash = ApiKey.hash_key(raw_key)
|
||||
try:
|
||||
api_key = ApiKey.objects.select_related("user").get(key_hash=key_hash)
|
||||
except ApiKey.DoesNotExist as exc:
|
||||
raise self.authentication_failed() from exc
|
||||
raise self.authentication_failed(request) from exc
|
||||
|
||||
if not api_key.matches_key(raw_key):
|
||||
raise self.authentication_failed()
|
||||
raise self.authentication_failed(request)
|
||||
|
||||
if not api_key.is_active_key:
|
||||
raise PermissionDenied(
|
||||
@@ -57,5 +58,6 @@ class ApiKeyAuthentication(BaseAuthentication):
|
||||
return self.keyword
|
||||
|
||||
@staticmethod
|
||||
def authentication_failed() -> AuthenticationFailed:
|
||||
def authentication_failed(request) -> AuthenticationFailed:
|
||||
throttle_api_auth_failure(request)
|
||||
return AuthenticationFailed(api_error("unauthorized", "缺失或无效 API Key"))
|
||||
|
||||
Reference in New Issue
Block a user