diff --git a/app_logger.py b/app_logger.py index b2e84c0..239d92c 100755 --- a/app_logger.py +++ b/app_logger.py @@ -7,6 +7,7 @@ import logging import os +import re from logging.handlers import RotatingFileHandler from datetime import datetime import threading @@ -45,6 +46,31 @@ class ColoredFormatter(logging.Formatter): return result +class SensitiveDataFilter(logging.Filter): + """对日志中的敏感字段做统一脱敏处理。""" + + _EMAIL_RE = re.compile(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b") + _PAIR_PATTERNS = ( + (re.compile(r"(?i)\b(password|passwd|pwd)\s*[:=]\s*([^,\s]+)"), r"\1=[REDACTED]"), + (re.compile(r"(?i)\b(token|csrf_token|session|authorization)\s*[:=]\s*([^,\s]+)"), r"\1=[REDACTED]"), + (re.compile(r"(?i)\b(user_id|admin_id|token_id)\s*=\s*\d+\b"), r"\1=[MASKED]"), + ) + + def filter(self, record: logging.LogRecord) -> bool: + try: + message = record.getMessage() + sanitized = self._EMAIL_RE.sub("[REDACTED_EMAIL]", message) + for pattern, replacement in self._PAIR_PATTERNS: + sanitized = pattern.sub(replacement, sanitized) + if sanitized != message: + record.msg = sanitized + record.args = () + except Exception: + # 日志过滤异常不应影响业务日志输出 + pass + return True + + def setup_logger(name='app', level=None, log_file=None, max_bytes=10*1024*1024, backup_count=5): """ 设置日志记录器 @@ -74,6 +100,17 @@ def setup_logger(name='app', level=None, log_file=None, max_bytes=10*1024*1024, # 清除已有的处理器(避免重复) logger.handlers.clear() + logger.filters.clear() + + # 全局敏感日志脱敏(默认开启,可通过 LOG_REDACT_SENSITIVE=0 关闭) + redact_enabled = str(os.environ.get("LOG_REDACT_SENSITIVE", "1")).strip().lower() in { + "1", + "true", + "yes", + "on", + } + if redact_enabled: + logger.addFilter(SensitiveDataFilter()) # 日志格式 detailed_formatter = logging.Formatter(