Apache 2.4 下无法直接提取特定 Cookie 值,需用 expr= 正则匹配或 SetEnvIf 预提取环境变量;二者均不自动解码,且须防敏感信息泄露与正则性能风险。

mod_log_config 本身不支持直接提取请求中某个特定 Cookie 的值(比如 auth_token 或 session_id),它只能记录整条 Cookie 请求头或 Apache 自己设置的跟踪 Cookie。真要审计用户行为并关联到具体 ID,得绕开“直接抽取”的幻想,用组合配置实现等效效果。
为什么 %{Cookie}i 和 %{cookie}n 都不能直接拿到 auth_token=xxx 的值
因为 %{Cookie}i 只是原样输出整个请求头字符串(如 auth_token=abc123; user_id=456; _ga=...),而 %{cookie}n 在 Apache 2.4+ 中已失效——mod_usertrack 被彻底移除,CookieTracking On 会报错或留空。你查日志时看到的永远是整串、空值、或根本没这字段。
Apache 2.4 下安全提取 auth_token 的唯一可行路径:expr= + 正则匹配
从 Apache 2.4.13 开始,LogFormat 支持 expr= 表达式语法,可对请求头做简单正则提取。但注意:它不解析 URL 编码,也不做 Cookie 解析,只是字符串匹配。
LogFormat "%h %t \"%r\" %>s %{expr=%{HTTP_COOKIE} =~ /auth_token=([^;]+)/ ? $1 : '-'}e" auth_log- 这个表达式只在
HTTP_COOKIE头存在且含auth_token=xxx时取第一个捕获组;否则填- - 如果值含 URL 编码(如
auth_token=abc%3D123),正则仍能匹配,但日志里写的是原始编码串,不是解码后内容 - 多个同名 Cookie(极少见)只会匹配第一个;大小写敏感,
Auth_Token不会被捕获
更可靠的做法:用 mod_setenvif + mod_headers 预先提取并设环境变量
比在 LogFormat 里硬写正则更稳定,也避免每次请求都跑一遍 regex。核心是把提取逻辑提前到请求处理早期:
- 用
SetEnvIf检查Cookie请求头,用正则捕获并存入环境变量:SetEnvIf Cookie "(^|;\s*)auth_token=([^;]+)" AUTH_TOKEN=$2 - 再在
LogFormat中直接引用:LogFormat "%h %t \"%r\" %>s %{AUTH_TOKEN}e" auth_log - 注意:
SetEnvIf对空格和分号前导符做了兼容(\s*),但依然不处理 URL 解码;若业务端发的 token 是编码过的,需应用层保证一致性 - 该方式在
mod_setenvif启用前提下稳定工作,不依赖expr=,兼容性更好
别踩这些坑:脱敏、性能与日志爆炸
真实生产环境里,光“能取出来”远远不够:
- Cookie 值常含敏感信息(JWT、token),直接记进日志违反 GDPR/等保要求;务必在
LogFormat中加条件过滤,例如只记录非空且长度在合理范围内的值:%{expr=%{ENV:AUTH_TOKEN} != '' && length(%{ENV:AUTH_TOKEN}) < 200 ? substr(%{ENV:AUTH_TOKEN},0,32) : '-'}e - 正则匹配在高并发下有轻微开销,
SetEnvIf方式比expr=略快,但两者差异不大;真正要防的是错误正则导致 Apache 进程卡死(比如回溯爆炸),务必测试边界 case - 不要在
CustomLog中混用多个%{...}e引用未定义环境变量,会导致该字段输出为空字符串而非-,干扰后续 awk/grep 分析


















