Nginx 默认不支持直接记录 $request_body,需通过 proxy_pass 触发读取或使用 Lua 模块主动调用 ngx.req.read_body(),配合自定义日志格式及合理缓冲设置方可安全审计 POST 内容。

在 Nginx 中直接记录 $request_body 并不默认支持,因为请求体可能被缓冲、丢弃或未读取,需配合特定模块和配置才能安全、可靠地审计 POST 请求内容。
启用 ngx_http_proxy_module 或 ngx_http_lua_module 支持
Nginx 官方模块中,$request_body 变量仅在请求体已被读取并缓存时才有效。默认情况下,Nginx 为性能考虑不会主动读取请求体(尤其大文件上传时)。因此需显式触发读取:
- 使用
proxy_pass时,添加proxy_set_body $request_body;或确保后端代理前已读取体(如通过proxy_buffering off;+client_max_body_size合理设置) - 更稳妥的方式是引入
ngx_http_lua_module(OpenResty),用ngx.req.read_body()主动读取,再通过ngx.var.request_body获取内容
配置自定义日志格式并启用 body 记录
在 http 或 server 块中定义日志格式,注意避免记录敏感字段(如密码、token):
log_format audit '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'req_body:"$request_body"';
然后在 location 中启用该格式,并确保请求体可用:
- 对需要审计的接口(如
/api/),添加client_body_buffer_size 128k;和client_max_body_size 1m;防止截断 - 若用 Lua,可加
access_by_lua_block { ngx.req.read_body() }确保变量就绪 - 避免在全局或高流量 location 使用,防止日志膨胀和性能下降
规避常见陷阱
直接记录 $request_body 容易失败或产生空值,原因包括:
- 请求体未被 Nginx 读取(例如未触发代理、未调用 Lua 读取)→ 日志中显示为空或 “-”
- 请求体过大超出缓冲区 → 被写入临时文件,
$request_body不再可用 - 含二进制或非 UTF-8 内容(如文件上传、图片 base64)→ 导致日志乱码甚至截断,建议只对
application/json或application/x-www-form-urlencoded类型开启 - POST 表单被浏览器自动转为 GET(如重定向)→ 实际无 body,日志无意义
替代方案:结合应用层审计更可靠
纯 Nginx 层记录 body 存在局限,生产环境推荐组合策略:
- 在业务应用中解析并记录关键字段(如订单号、用户 ID、操作类型),脱敏后写入审计库
- Nginx 仅记录元数据:IP、URI、Method、Content-Type、Content-Length、响应状态、耗时
- 必要时用
mirror模块将请求镜像到专用审计服务,由其完整解析 body 并留存










