87 lines
2.7 KiB
Python
87 lines
2.7 KiB
Python
from fastapi import Request
|
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
import time
|
|
from app.core.logger import log_request_async
|
|
from app.core.security import verify_token, decode_jwt
|
|
import json
|
|
import copy
|
|
|
|
class RequestLoggerMiddleware(BaseHTTPMiddleware):
|
|
LOGGED_METHODS = {"POST", "PUT", "DELETE"}
|
|
SENSITIVE_PATHS = {
|
|
"/api/user/login",
|
|
"/api/user/password-login",
|
|
"/api/user/reset-password"
|
|
}
|
|
SENSITIVE_FIELDS = {"password", "verify_code", "old_password", "new_password"}
|
|
|
|
def filter_sensitive_data(self, data: dict, path: str) -> dict:
|
|
"""过滤敏感数据"""
|
|
if not data or path not in self.SENSITIVE_PATHS:
|
|
return data
|
|
|
|
filtered_data = copy.deepcopy(data)
|
|
for field in self.SENSITIVE_FIELDS:
|
|
if field in filtered_data:
|
|
filtered_data[field] = "***"
|
|
return filtered_data
|
|
|
|
async def dispatch(self, request: Request, call_next):
|
|
method = request.method
|
|
|
|
if method not in self.LOGGED_METHODS:
|
|
return await call_next(request)
|
|
|
|
start_time = time.time()
|
|
path = request.url.path
|
|
headers = dict(request.headers)
|
|
query_params = dict(request.query_params)
|
|
|
|
# 获取并过滤请求体
|
|
body = None
|
|
try:
|
|
body_bytes = await request.body()
|
|
if body_bytes:
|
|
body = json.loads(body_bytes)
|
|
body = self.filter_sensitive_data(body, path)
|
|
print(f"请求体: {body}")
|
|
except:
|
|
pass
|
|
|
|
# 从 Authorization 头获取 token
|
|
# token = None
|
|
# auth_header = headers.get('authorization')
|
|
# if auth_header and auth_header.startswith('Bearer '):
|
|
# token = auth_header.split(' ')[1]
|
|
|
|
# # 从 token 获取用户信息
|
|
# user_id = None
|
|
# if token:
|
|
# try:
|
|
# payload = decode_jwt(token)
|
|
# if payload:
|
|
# user_id = payload.get("phone")
|
|
# except:
|
|
# pass
|
|
|
|
# 处理请求
|
|
response = await call_next(request)
|
|
|
|
# 计算响应时间
|
|
response_time = int((time.time() - start_time) * 1000)
|
|
|
|
# 异步记录日志
|
|
log_data = {
|
|
"path": path,
|
|
"method": method,
|
|
"headers": headers,
|
|
"query_params": query_params,
|
|
"body": body,
|
|
# "user_id": user_id,
|
|
"ip_address": request.client.host,
|
|
"status_code": response.status_code,
|
|
"response_time": response_time
|
|
}
|
|
log_request_async(log_data)
|
|
|
|
return response |