1. Add 登陆功能
2. 调整字体大小 3. 新增部分功能
This commit is contained in:
56
backend/app/api/middleware/audit.py
Normal file
56
backend/app/api/middleware/audit.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""Audit logging middleware.
|
||||
|
||||
Logs every API request with method, path, status code, response time,
|
||||
and the authenticated user identity (extracted from the JWT when present).
|
||||
Log lines are structured so they can be ingested by ELK / Loki.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
from fastapi import Request, Response
|
||||
from loguru import logger
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
|
||||
class AuditMiddleware(BaseHTTPMiddleware):
|
||||
"""Log all API calls. Skips health/docs paths to reduce noise."""
|
||||
|
||||
# Paths that produce no audit log entry.
|
||||
_SKIP_PREFIXES = ("/health", "/docs", "/redoc", "/openapi.json")
|
||||
|
||||
async def dispatch(self, request: Request, call_next) -> Response:
|
||||
"""Intercept the request, call the handler, and log the outcome."""
|
||||
path = request.url.path
|
||||
if path == "/" or any(path == p or path.startswith(p + "/") for p in self._SKIP_PREFIXES):
|
||||
return await call_next(request)
|
||||
|
||||
start = time.perf_counter()
|
||||
response = await call_next(request)
|
||||
elapsed_ms = int((time.perf_counter() - start) * 1000)
|
||||
|
||||
# Extract user identity from JWT header for structured audit records.
|
||||
# The token is not re-validated here — auth dependencies do that upstream.
|
||||
user_id = "anonymous"
|
||||
username = "anonymous"
|
||||
auth_header = request.headers.get("authorization", "")
|
||||
if auth_header.startswith("Bearer "):
|
||||
try:
|
||||
from app.shared.bootstrap import get_jwt_handler
|
||||
claims = get_jwt_handler().decode_token(auth_header[7:])
|
||||
user_id = claims.user_id
|
||||
username = claims.username
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
logger.info(
|
||||
"AUDIT method={} path={} status={} elapsed_ms={} user_id={} username={}",
|
||||
request.method,
|
||||
path,
|
||||
response.status_code,
|
||||
elapsed_ms,
|
||||
user_id,
|
||||
username,
|
||||
)
|
||||
return response
|
||||
Reference in New Issue
Block a user