Nginx rewrite中安全传递GET参数需主动构造query string:默认保留易致语法错误、敏感参数泄露或格式混乱;应使用$args显式拼接、set+map精确过滤/重命名,避免if+set拼参陷阱。

在 Nginx 的 rewrite 中安全传递 GET 请求参数,核心在于明确控制 query string 的生成方式——不能依赖默认保留,而要主动构造或显式拼接,避免参数丢失、注入或重复。
理解 rewrite 对参数的默认行为
rewrite 默认只改写 URI 路径部分,原始 query string(如 ?a=1&b=2)会自动追加到新 URI 后。这看似方便,但容易引发问题:
- 若目标路径本身已含问号(如
/api?uid=100),再叠加原参数会导致语法错误(/api?uid=100?a=1&b=2) - 无法剔除敏感参数(如
token、debug) - 无法统一升级参数格式(如把
v=1替换为v=2)
用 $args 显式拼接最稳妥
将新 URI 和完整参数分开构造,再用 $args 变量显式拼入,可完全掌控参数内容:
- 直接转发全部参数:
rewrite ^/old/(.*)$ /new/$1?$args last; - 只传指定参数:
rewrite ^/user/(\d+)$ /profile?id=$1?$args last;(仅带原始参数) - 清空参数并重设:
rewrite ^/login$ /auth?source=nginx redirect;(不带原参数)
用 set + map 精确控制参数组合
当需过滤、替换或条件拼接时,set 配合 map 更安全可靠:
- 提取并重命名参数:
set $uid $arg_id; rewrite ^/user$ /profile?uid=$uid last; - 用 map 过滤敏感字段(推荐用于生产):
map $arg_token $safe_token { default ""; "" ""; }
map $arg_debug $safe_debug { default ""; "" ""; }rewrite ^/api/(.*)$ /v2/api/$1?token=$safe_token&debug=$safe_debug last;
避免 if + set 拼参的陷阱
不要在 if 块中用多个 set 拼接 $args,因为 if 在 location 中有执行限制,且变量作用域易出错。例如以下写法不可靠:
- ❌
if ($arg_v) { set $args "v=$arg_v"; } if ($arg_t) { set $args "$args&t=$arg_t"; } - ✅ 改用
map预定义逻辑,或用 Lua(Nginx Plus 或 OpenResty)做复杂参数处理











