扩展现有的位置配置而不是覆盖它

扩展现有的位置配置而不是覆盖它

我拥有的

我已将 Nginx 配置为处理所有虚拟主机的 .php 文件,并且一切运行正常。

location ~ \.php {
    include snippets/fastcgi-php.conf;
    keepalive_timeout 0;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}

以上内容位于snippets/common.conf并包含在每个虚拟主机配置中。 前面提到的内容fastcgi-php.conf位于其旁边。

我需要的

对于给定的虚拟主机,我需要拒绝除之外的所有文件的访问/example.php

我尝试过

  1. location ~ ^/example {
        allow all;
    }
    location ~ ^/ {
        allow 123.123.123.123;
        deny all;
    }
    

    限制本身工作正常,但现在 PHP 文件作为源文本返回,而不是被处理。这意味着上面的内容以某种方式覆盖了之前的location ~ \.php,尽管我甚至没有.php在这里包含扩展。

  2. 创造common-php.conf

    include snippets/fastcgi-php.conf;
    keepalive_timeout 0;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    

    重复使用common.conf

    location ~ \.php {
        include snippets/common-php.conf;
    }
    

    在我的实际虚拟主机配置中:

    location ~ ^/example {
        allow all;
        include snippets/common-php.conf;
    }
    location ~ ^/ {
        allow 123.123.123.123;
        deny all;
        include snippets/common-php.conf;
    }
    

    上述问题在于:

    • 它使设置变得非常复杂
    • /example.php配置两次似乎多余
    • 它没有完全工作,因为我/plugins/Feedback/angularjs/feedback-popup/feedback-popup.directive.html?cb=abcd1234出于某种原因在 eg 上得到了 403。我使用的 CMS 很复杂,由于前两个原因,我没有进一步调查。

我想配置对/example.php文件的访问,但不覆盖它所附加的现有 PHP 处理程序。这可能吗?还是包含是我唯一的选择?

如果您能想到更好的配置来完成这项任务,请告诉我。谢谢!

答案1

也就是说,一个非常常见的错误是这样做

location / {
    ... some settings
}
location /admin {
    ... additional settings
}

并期望该/admin/...请求将使用组合设置。但事实并非如此,根据请求最终被处理的位置,只会应用一个设置集。然而,正如我已经每个请求都可以遍历多个位置块,并且可以使用变量操作来实现一些技巧。当请求经过不同的位置时,某个变量可能会被多次更改,并且其实际值可以在最终位置用作某些指令参数。本问题解决方案不会使用这种技术,但在其他一些情况下是可能的。

很多东西(例如条件标头)都可以使用(非常强大的)nginx 功能来实现。 /规则map的替代方案可以通过结合以下方式实现:allowdenymapgeo块来评估一个变量,作为一个标志来指示请求是否应该被阻止(可以找到一些更通用的例子这里):

map $uri $restricted {
    /example.php     0;
    default          1;
}
geo $deny {
    123.123.123.123  0;
    default          $restricted;
}

现在要决定是否应该阻止请求,您可以使用以下if阻止:

if ($deny) { return 403; }

它可以放置在级别server或 PHP 处理程序位置。但是,将其放置在级别server会更理想,因为它将在更早的位置执行,NGX_HTTP_SERVER_REWRITE_PHASE而不是在NGX_HTTP_REWRITE_PHASE

如果由于某种原因您想要添加基本身份验证而不是 IP 过滤,则可以使用以下技巧来实现:

map $uri $restricted {
    /example.php     off;
    default          "Protected area";
}
geo $realm {
    123.123.123.123  off;
    default          $restricted;
}
location ~ \.php$ {
    auth_basic $realm;
    auth_basic_user_file /path/to/.htpasswd;
    ...
}

相关内容