fix(security): P0 - 日志过滤敏感参数(token/password/secret等)

This commit is contained in:
2026-06-26 17:43:35 +08:00
parent 8dd5b691bf
commit 0e4a07f0c1
+56 -2
View File
@@ -3,13 +3,60 @@
"""
import logging
import re
import time
from typing import Optional
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware
logger = logging.getLogger(__name__)
# 敏感参数名称模式(不区分大小写)
SENSITIVE_PARAM_PATTERNS = re.compile(
r'^(password|passwd|pwd|token|secret|key|authorization|auth|api_key|apikey|'
r'access_token|refresh_token|accesstoken|refreshtoken|'
r'session_id|sessionid|sid|cookie|csrf|xsrf|bearer)$',
re.IGNORECASE
)
def filter_sensitive_params(query_string: Optional[str]) -> Optional[str]:
"""
过滤 query string 中的敏感参数
Args:
query_string: 原始 query string,例如 "name=xxx&password=secret&token=abc"
Returns:
过滤后的 query string,敏感参数的值被替换为 "***"
如果 query_string 为空或 None,返回原始值
"""
if not query_string:
return query_string
if query_string.startswith('?'):
query_string = query_string[1:]
if not query_string:
return query_string
parts = query_string.split('&')
filtered_parts = []
for part in parts:
if '=' in part:
key, value = part.split('=', 1)
if SENSITIVE_PARAM_PATTERNS.match(key):
filtered_parts.append(f"{key}=***")
else:
filtered_parts.append(part)
else:
# 没有 = 的参数,保留原样
filtered_parts.append(part)
return '&'.join(filtered_parts)
class RequestLoggingMiddleware(BaseHTTPMiddleware):
"""请求日志中间件"""
@@ -18,8 +65,15 @@ class RequestLoggingMiddleware(BaseHTTPMiddleware):
# 记录请求开始时间
start_time = time.time()
# 记录请求信息
logger.info(f"Request: {request.method} {request.url.path}")
# 过滤 query string 中的敏感参数
raw_query = str(request.url.query) if request.url.query else ""
safe_query = filter_sensitive_params(raw_query)
# 记录请求信息(不包含敏感参数)
if safe_query:
logger.info(f"Request: {request.method} {request.url.path}?{safe_query}")
else:
logger.info(f"Request: {request.method} {request.url.path}")
# 处理请求
response = await call_next(request)