最直白的验证方式是触发审计动作后实时查看日志:登录失败后执行tail -f /var/log/myapp/audit.log,需确保日志路径在Web根目录外、每行以\n结尾、使用正确的Monolog channel。

直接检查日志文件是否写入新内容
最直白的验证方式:触发一次明确的审计动作(比如登录失败、删除某条数据),然后立刻 tail -f /var/log/myapp/audit.log 查看是否有对应行。注意三点:
– 日志路径必须在 Web 根目录外,否则可能因权限或路由被拦截;
– 每条日志末尾必须有 \n,否则多条挤成一行,grep user_login 会漏匹配;
– 如果用 Monolog,确认你调用的是 $auditLogger->info() 而非 $logger->info(),channel 名不一致会导致日志进错文件。
用 Monolog 的 Handler 状态反查是否挂载成功
在任意可执行的 PHP 脚本里插入以下代码并访问:
$handlers = $auditLogger->getHandlers(); var_dump(array_map(fn($h) => get_class($h), $handlers));
输出中应包含 Monolog\Handler\StreamHandler。如果为空数组,说明:
– $auditLogger 实例没被正确创建或复用了普通 logger;
– 或 pushHandler() 调用位置太晚(比如放在某个条件分支里,实际没走到);
– 或 handler 初始化时路径不可写,但 Monolog 默认静默失败,不会抛异常。
抓取并发场景下的日志丢失现象
单次写入成功不代表审计稳定。用 ab -n 50 -c 10 http://localhost/login.php 模拟 10 并发登录失败请求,再检查日志行数是否为 10。若少于 10 行,说明:
– 仍在用 file_put_contents(..., FILE_APPEND | LOCK_EX),LOCK_EX 在高并发下排队阻塞,部分请求超时或被 Nginx 中断;
– 或未启用 StreamHandler 的 buffering(Monolog 8+ 默认开启,旧版需手动配置);
– 或日志路径所在磁盘已满、inode 耗尽,error_log() 会静默丢弃,但 StreamHandler 会抛 UnexpectedValueException——得看 PHP 错误日志才能发现。
立即学习“PHP免费学习笔记(深入)”;
确认敏感字段没被意外记录
审计日志里出现明文密码、token 或完整用户上下文,不是“生效了”,而是“生效得过头了”。重点检查:
– LineFormatter 是否启用了 %context%,而 $context 数组里混入了 $_POST['password'];
– 是否在记录前做过滤,例如:unset($context['password'], $context['token']);
– filter_var($input, FILTER_SANITIZE_STRING) 已被弃用,PHP 8.4+ 会报 Deprecated,改用 htmlspecialchars() 或正则白名单清洗。
tail 确认。



















