feat: harden phase 3 api security

This commit is contained in:
QiuSW
2026-07-03 10:34:37 +08:00
parent 1c5aa7845d
commit 0168aa30ba
19 changed files with 540 additions and 46 deletions
+8 -6
View File
@@ -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"))