关键在于日志中敏感信息的前置脱敏而非禁用日志:在输入层拦截并清洗外部请求参数,结构化日志中显式排除敏感字段,二次过滤与加密传输保障存储安全,按环境动态控制敏感字段输出。

关键不是“不让日志记录”,而是“不让敏感信息以明文形式进入日志流”。日志本身必须保留可追溯性,但需在写入前完成识别、过滤和脱敏。
输入层就做清洗:拦截原始敏感数据
用户输入、请求参数、响应体是敏感信息最常出现的位置。不能等它进日志再处理,得在入口处截住。
- 对所有外部输入(如
$_GET、$_POST、HTTP头)做统一预处理,用filter_var()或正则匹配剔除/替换已知敏感模式(如身份证号、手机号、JWT token、银行卡号) - 避免直接拼接日志字符串:
error_log("User: " . $_POST['password']);是高危写法;应改用结构化日志并显式排除字段 - 使用中间件或请求生命周期钩子,在路由分发前完成敏感键值的剥离(例如删除
password、token、auth_code等字段)
日志格式化阶段强制脱敏
即使上游没拦干净,也要在日志生成环节做二次过滤。结构化日志(如 JSON)比纯文本更容易控制输出内容。
- 自定义日志处理器,对日志上下文(context)中的每个字段做白名单校验,只允许业务必需字段写入
- 对常见敏感字段名(如
password、api_key、credit_card)做正则匹配并替换为[REDACTED] - 使用现成库如
monolog的NormalizerFormatter+ 自定义Processor,在序列化前擦除敏感值
存储与传输环节设防
日志一旦落地,就要防止它成为新的泄露面。
- 禁止将日志目录放在 Web 根目录下(如
/var/www/logs/),应设为/var/log/myapp/并确保权限为640,仅限应用用户和 syslog 组访问 - 若用远程日志(如 Syslog、ELK、Loki),必须启用 TLS 加密传输,避免日志在网络中被嗅探
- 不使用
file://或stdout直接输出含敏感字段的原始调试日志;生产环境关闭display_errors和详细错误堆栈
运行时动态控制日志级别与字段
不同环境对日志的“精细度”要求不同,应支持按需开关敏感字段输出。
- 通过环境变量(如
LOG_SENSITIVE_FIELDS=false)控制是否记录用户身份类字段 - 在 CI/CD 中注入不同配置:开发环境可记录完整请求体,生产环境只记录 trace_id + status + duration
- 对审计类日志(如登录、支付)单独建通道,走加密落盘或专用安全日志服务,与其他业务日志物理隔离











