优化鉴权系统

This commit is contained in:
2026-07-03 21:54:19 +08:00
parent 7e65fadd83
commit 98a92b83fa
11 changed files with 539 additions and 149 deletions
+8 -20
View File
@@ -1,31 +1,19 @@
from dataclasses import dataclass
import hmac
from typing import Annotated
from fastapi import Depends, HTTPException, Request, Security, status
from fastapi.security import APIKeyHeader
from users import AuthenticatedUser, UserStore
api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
@dataclass(frozen=True, slots=True)
class AuthenticatedUser:
user_id: str
class ApiKeyAuthenticator:
def __init__(self, whitelist: dict[str, str]) -> None:
if not whitelist:
raise ValueError("API_KEY_WHITELIST must contain at least one user")
self._whitelist = whitelist.copy()
def __init__(self, user_store: UserStore) -> None:
self._user_store = user_store
def authenticate(self, api_key: str | None) -> AuthenticatedUser | None:
if not api_key:
return None
for user_id, allowed_key in self._whitelist.items():
if hmac.compare_digest(api_key, allowed_key):
return AuthenticatedUser(user_id=user_id)
return None
async def authenticate(self, api_key: str | None) -> AuthenticatedUser | None:
return await self._user_store.authenticate(api_key)
async def require_api_key(
@@ -33,7 +21,7 @@ async def require_api_key(
api_key: Annotated[str | None, Security(api_key_header)],
) -> AuthenticatedUser:
authenticator: ApiKeyAuthenticator = request.app.state.authenticator
user = authenticator.authenticate(api_key)
user = await authenticator.authenticate(api_key)
if user is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
@@ -42,4 +30,4 @@ async def require_api_key(
return user
CurrentUser = Annotated[AuthenticatedUser, Depends(require_api_key)]
CurrentUser = Annotated[AuthenticatedUser, Depends(require_api_key)]