我有一个像这样的 API 端点/my/api/PARAM1/abcd?arg1=val1&arg2=val2
,并使用重定向代理到其他地方的 fastcgi 服务器(使用上游)。
基本上我有当前的配置:
location ~ "^/my/api/(?<api_name>[A-Z0-9]+)?$" {
rewrite ^ "/cgi-bin/apiserver?api_name=${api_name}&p1=${arg_arg1}&p2=${arg_arg2}" last;
}
location /cgi-bin/apiserver {
include fastcgi_params;
fastcgi_index myapiserver?*;
fastcgi_param SCRIPT_FILENAME /usr/lib/cgi-bin/myapiserver$fastcgi_script_name;
fastcgi_pass my_fcgi_upstream;
}
FCGI 服务器不是我能控制的,我不能更改查询字符串中的参数名称,也不能更改它运行的代码。我想保护它免受攻击,比如检查发送给它的 GET 参数的格式(在此示例中,发送为和)。检查它们是否为实数,arg1
或者字符串格式是否符合特定的正则表达式。arg2
p1
p2
理想情况下,我还想检查几个参数是否(p1, p2, p3, p4)
位于特定的白名单中(例如,(0,1,2,3)
允许但不允许(1,1,2,3)
。
对于第一个问题,我认为我们可以使用多个位置块或重写来实现某些功能,但我找不到正确的方法。对于第二个改进(参数白名单),我想我唯一的解决方案是依赖 nginx 中的某种 Lua 脚本?我想不惜一切代价避免在 FCGI 服务器和 nginx 之间使用某种应用代理,所以如果我可以在 nginx 中完成所有事情,那就太棒了!
谢谢您的帮助。
答案1
location
Nginx 在测试块或语句中的正则表达式时使用规范化的 URI rewrite
。参数在此阶段已被删除,并重新定位到$args
和$arg_
变量。
检验论点的唯一有效方法是用if
陈述,无论有没有一个map
区块。
您可以在配置中的任何位置检查参数,但假设您希望fastcgi_pass
尽可能接近地检查它,则可以将if ... { return ...; }
块放在块内location /cgi-bin/apiserver
。请注意,这是以下情况之一:在块if
内使用location
。
问题的最后一部分最好使用来实现,map
因为您可以将p1
、p2
和连接p3
成p4
一个字符串,然后将其传递给多个正则表达式。
例如:
map $arg_p1,$arg_p2,$arg_p3,$arg_p4 $fails {
~^1,2,3,4$ 0;
default 1;
}
server {
...
location /cgi-bin/apiserver {
if (fails) { return 403; }
...
}
}
您也可以使用同一张地图,在其他位置使用,分别测试p1
和。但这可能没有必要,因为它们必须是数字才能匹配白名单。p2
.*
注意map
必须将块放置在外部块server
。另外,请注意,正则表达式按顺序进行评估,直到找到匹配项。