默认Nginx不记录POST请求体,需显式启用$request_body变量并配合proxy_pass等指令;须配置自定义日志格式、限制请求体大小、调大client_body_buffer_size、脱敏敏感字段或改用mirror模块异步审计。

默认情况下,Nginx 不记录 POST 请求体(即请求参数),因为性能和安全考虑。若需用于接口回溯审计,必须显式开启并谨慎配置,避免日志膨胀、敏感信息泄露或服务性能下降。
启用 $request_body 变量记录原始请求体
Nginx 1.3.9+ 支持 $request_body 变量,但仅在请求体被读取后才可用——这通常发生在使用 proxy_pass、fastcgi_pass 等代理指令时(Nginx 自动读取 body);纯静态服务或未触发读取逻辑时该变量为空。
- 确保使用 proxy_pass(如转发到后端 API)或 fastcgi_pass,否则 $request_body 始终为空
- 在 http 或 server 块中定义自定义日志格式,例如:
log_format post_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$request_body"'; - 在 location 块中启用该格式:
access_log /var/log/nginx/post_audit.log post_log;
处理大请求体与截断风险
POST 数据可能很大(如文件上传、JSON 大包),直接全量记录易导致磁盘爆满、I/O 压力升高。建议限制长度并明确截断策略:
- 用 client_max_body_size 控制最大允许 Body 大小(如 1M),超出则返回 413
- 通过 log_format 中的 $request_body 默认只记录已缓存部分;若 body 超过 client_body_buffer_size(默认 8k),Nginx 会写入临时文件,此时 $request_body 为空 —— 必须调大该值(如设为 128k)并确保磁盘空间充足
- 生产环境推荐加前缀/后缀标记 + 截断,例如:
log_format post_log '... "$request_body_limit(2048)"';
(需配合第三方模块如 set-misc-nginx-module 的 set_quote_sql 或自定义 Lua 截断)
脱敏敏感字段,规避合规风险
用户密码、token、身份证号等绝不可明文落盘。Nginx 原生不支持字段级脱敏,需组合方案:
- 用 ngx_http_lua_module 在 log_by_lua_block 中解析 JSON 表单,对 key 匹配字段(如 "password", "id_card")替换为 "***"
- 示例片段(需启用 lua 模块):
log_by_lua_block {
local json = require "cjson"
if ngx.var.request_method == "POST" and ngx.var.content_type and string.find(ngx.var.content_type, "application/json") then
local data = json.decode(ngx.var.request_body)
if data and type(data) == "table" then
data.password = "***"
data.token = "***"
ngx.var.request_body = json.encode(data)
end
end
} - 更稳妥方式:不在 Nginx 层记录原始 body,改由后端应用统一采集、脱敏、上报审计日志
替代方案:用 mirror 模块异步镜像请求到审计服务
避免阻塞主请求流,适合高并发场景:
- 启用 ngx_http_mirror_module(Nginx 1.13.4+ 内置)
- 配置 mirror location 将完整请求(含 body)复制一份发往内部审计服务:
location / {
mirror /mirror;
proxy_pass http://backend;
}
location = /mirror {
internal;
proxy_pass http://audit-service$request_uri;
proxy_pass_request_body on;
} - 审计服务接收后解析、校验、脱敏、存储,Nginx 无日志膨胀和性能负担











