Apache 如何合并多个匹配的位置部分

Apache 如何合并多个匹配的位置部分

我正在处理一些基本的 Apache 配置,但我不明白<Location>当多个部分与传入请求 URL 匹配时,Apache 如何合并不同的部分。Apache 文档在其“如何合并部分”一章中,当涉及到同一类型的几个匹配部分的顺序/优先级时,有点令人困惑。

例如,想象以下 apache 配置(忽略实际内容是否有意义,我只对每个规则/部分的应用顺序感兴趣):

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>

现在,如果客户端发出请求/sub/foobar,那么应用于该请求的最终配置是什么?

应用的配置是否相当于:

# All the directives contained in all the matchin Locations in declaration order
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order allow,deny
Order deny,allow
Require valid-user
Satisfy all

或者可能

# same as above, but with longest matching path last
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order deny,allow
Require valid-user
Satisfy all
Order allow,deny

或者一些完全不同的东西。

谢谢您的帮助,我真的很困惑。

答案1

合并的顺序相当复杂,而且很容易出现异常……apache 文档是“如何合并各部分

根据该文档,合并部分的顺序是通过按照在配置文件中遇到的顺序处理每种匹配类型的所有匹配条目来完成的,最后的匹配获胜。(<Directory> 除外,它按路径特定性的顺序进行处理)。

类型的顺序为DirectoryDirectoryMatchFiles和 最后Location。后面的匹配将覆盖前面的匹配。(*ProxyPass 和 Alias 再次被区别对待,请参阅最后的注释)

并且,在使用 ProxyPass 和 <Location> 部分中的 ProxyPass 时,这些规则有几个重要的例外。(见下文)

因此,从你上面的例子请求http://somehost.com/sub/foobar使用以下配置;

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>

它将积累以下指令....

  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
  Order allow,deny
  Order deny,allow
  Require valid-user
  Satisfy all   

随着后面的匹配消除了之前的重复,结果是;

  ProxyPass http://backend.com/
  Order deny,allow
  Require valid-user
  Satisfy all   

解释
<Directory>后面的匹配会覆盖前面的匹配,但匹配按以下顺序处理的情况 除外:从最短的目录组件到最长的目录组件。

举例来说, 无论在配置中指定这些指令的顺序如何,
<Directory /var/web/dir>
都会先进行处理,并且更具体的匹配将获胜。
<Directory /var/web/dir/subdir>

任何匹配的Location指令都会始终覆盖先前匹配的Directory指令。

基本思想是,对于像内部这样的请求,GET /some/http/request.html它将通过 转换为文件系统中的位置Alias,或者转换为与其匹配的 VirtualHost ScriptAlias下的普通文件位置。DocumentRoot

因此,请求将具有以下用于匹配的属性:
Location: /some/http/request.html File: /var/www/html/mysite/some/http/request.html Directory: /var/www/html/mysite/some/http

然后,Apache 将按照目录特定性的顺序依次应用配置中的所有Directory匹配项,然后按照遇到的顺序依次应用DirectoryMatch、、Files最后匹配。Location

因此,Location将覆盖Files,后者将覆盖DirectoryMatch,路径匹配Directory优先级最低。因此,在上面的示例中,对 的请求/sub/foobar将按顺序匹配前 3 个位置,因此对于冲突的指令,最后一个位置获胜。

(您说得对,从文档中无法清楚地看出某些边缘情况是如何解决的,任何allow from *类型指令都可能与关联的相连Order allow,deny,但我没有测试过。此外,如果您匹配Satisfy Any但之前已经收集了Allow from *...会发生什么情况)

关于 ProxyPass 和 Alias 的有趣说明

只是有点烦人,ProxyPass而且Alias似乎在另一个方向上起作用....;-) 它基本上击中了第一个匹配,然后停止并使用它!

Ordering ProxyPass Directives

The configured ProxyPass and ProxyPassMatch rules are 
checked in the order of configuration. 
The first rule that matches wins. So
usually you should sort conflicting ProxyPass rules starting with the
longest URLs first. Otherwise later rules for longer URLS will be
hidden by any earlier rule which uses a leading substring of the URL.
Note that there is some relation with worker sharing.

For the same reasons exclusions must come before the general 
ProxyPass directives.

所以基本上,必须指定 Alias 和 ProxyPass 指令,最具体的先指定;

Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo"     "/srv/www/common/foo"

ProxyPass "/special-area" "http://special.example.com" smax=5 max=10
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On

但是,正如 @orev 指出的那样。您可以在 Location 指令中使用 ProxyPass 指令,因此 Location 中更具体的 ProxyPass 将胜过任何先前找到的 ProxyPass。

答案2

如果您嵌套部分(例如):嵌套部分将在相同类型的非嵌套部分之后合并。这意味着如果您将块添加到非嵌套配置,您的最后匹配部分将发生变化。

相关内容