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


35

我正在研究一些基本的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

或完全不同的东西。

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

Answers:


44

合并的顺序非常复杂,很容易被异常所吸引... apache文件是“ 如何合并各节

根据该文档,节的合并顺序是通过按配置文件中遇到的顺序处理每种匹配类型的所有匹配项,然后移至下一个类型(<Directory除外)来完成的。 >,按路径特异性的顺序进行处理)。

类型的顺序是DirectoryDirectoryMatchFiles,和最后Location。之后的比赛会覆盖之前的比赛。(* ProxyPass和Alias再次区别对待,请参阅末尾的注释)

这些规则有几个重要的例外,它们适用于<Location>部分中的ProxyPass和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内部这样的请求,它将通过转换为文件系统中的某个位置AliasScriptAlias或者DocumentRoot将其匹配的VirtualHost转换为文件下的正常文件位置。

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

那么Apache将适用于把所有的的Directory比赛中,在目录特异性的顺序,从配置,然后依次应用DirectoryMatchFiles以及最后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。


3
感谢您标记有关订购ProxyPass指令的警告。为我省去了很多头痛
杰里米·法兰西

2
关于ProxyPass “朝着另一个方向工作”,只有当他们不在时,这才是正确的<Location>。在里面<Location>,遵循合并规则<Location>,这意味着您希望最不特定的<Location>指令排在较特定的指令之前。这允许更具体的指令覆盖较不具体的指令。ProxyPass每个只能有一个<Location>
orev 18/09/14
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.