nginx可通过map+log_format+正则实现静态资源访问日志字段级实时脱敏:一、用map预定义规则提取并掩码手机号、uid、token等敏感字段;二、在log_format中引用脱敏变量;三、仅对.js/.css等静态资源location启用该日志格式;四、需测试多参数、空值等边界场景,确保default分支兜底且性能无影响。

静态资源访问日志中常包含敏感信息(如用户 ID、设备指纹、URL 中的 token 或手机号),直接记录存在合规风险。Nginx 本身不支持动态内容脱敏,但可通过 log_format + map + 正则提取 + 变量替换 的组合,在日志写入前完成字段级实时脱敏,无需后处理或外部程序。
一、用 map 模块预定义脱敏规则
Nginx 的 map 指令可在请求处理早期对变量做映射,适合用于正则匹配并生成脱敏值。例如,从 URL 中提取手机号并掩码:
map $request_uri $masked_phone {
~(?<p>说明:<br>
- 正则使用命名捕获组 <code>(? 确保只匹配 <code>/user/13812345678.</code> 类路径中的号码;<br>
- 匹配成功时将原号码转为 <code>"13812345678:****"</code>(保留前3位+后4位标识,中间掩码);<br>
- 不匹配则设为短横线,避免空值干扰日志结构。</code></p><h3>二、构造脱敏型 log_format</h3><p>在 <code>http</code> 块中定义新日志格式,引用脱敏变量而非原始字段:</p><pre class="brush:php;toolbar:false;">log_format secure_static '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'uid="$masked_uid" phone="$masked_phone" token="$masked_token";对应需提前定义其他脱敏变量,例如:
-
map $args $masked_uid { ~uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12}) "$1"; default "-"; }—— 掩码 UUID 格式用户 ID -
map $arg_token $masked_token { ~^([a-zA-Z0-9]{4}).* "$1****"; default "-"; }—— 截取 token 前4位并掩码其余
三、精准作用于静态资源 location
避免全局脱敏影响动态接口,仅对 .js、.css、.png 等静态路径启用该日志格式:
location ~* \.(js|css|png|jpg|gif|ico|woff2?)$ {
access_log /var/log/nginx/static_access.log secure_static;
expires 1h;
add_header Cache-Control "public, immutable";
}
注意:
- 使用 ~* 忽略大小写匹配;
- 不要在此 location 中使用 rewrite 或 proxy_pass,否则可能改变 $request_uri 或参数变量行为,导致 map 失效;
- 若静态资源由 upstream 提供,需确保上游未修改原始请求头或 URI。
四、验证与边界处理
上线前需测试脱敏逻辑是否覆盖常见变体:
- URL 中含多个参数(如
/a.js?uid=abc&token=xyz)→ 各 map 应独立生效 - 手机号出现在 query string 而非 path → 调整
map的源变量为$args或$request_uri - 空值或异常格式(如
phone=abc)→default分支必须明确,防止日志中出现未定义变量(显示为“-”更安全) - 高并发下性能影响极小——map 查找是 O(1) 哈希操作,正则仅在匹配时执行,且 Nginx 编译后缓存编译结果
可通过 nginx -t 验证配置,再用 curl 发送测试请求并检查日志输出是否符合预期。











