fix(security): P0 - 日志过滤敏感参数(token/password/secret等)
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user