Nginx:使用正则表达式检查参数格式并进行重写

Nginx:使用正则表达式检查参数格式并进行重写

我有一个像这样的 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或者字符串格式是否符合特定的正则表达式。arg2p1p2

理想情况下,我还想检查几个参数是否(p1, p2, p3, p4)位于特定的白名单中(例如,(0,1,2,3)允许但不允许(1,1,2,3)

对于第一个问题,我认为我们可以使用多个位置块或重写来实现某些功能,但我找不到正确的方法。对于第二个改进(参数白名单),我想我唯一的解决方案是依赖 nginx 中的某种 Lua 脚本?我想不惜一切代价避免在 FCGI 服务器和 nginx 之间使用某种应用代理,所以如果我可以在 nginx 中完成所有事情,那就太棒了!

谢谢您的帮助。

答案1

locationNginx 在测试块或语句中的正则表达式时使用规范化的 URI rewrite。参数在此阶段已被删除,并重新定位到$args$arg_变量。

检验论点的唯一有效方法是用if陈述,无论有没有一个map区块

您可以在配置中的任何位置检查参数,但假设您希望fastcgi_pass尽可能接近地检查它,则可以将if ... { return ...; }块放在块内location /cgi-bin/apiserver。请注意,这是以下情况之一:在块if内使用location

问题的最后一部分最好使用来实现,map因为您可以将p1p2和连接p3p4一个字符串,然后将其传递给多个正则表达式。

例如:

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。另外,请注意,正则表达式按顺序进行评估,直到找到匹配项。

相关内容