配置部分
Configuration Section Containers 的类型
相关模块 | 相关指令 |
核心 modversion mod_proxy | <Directory> <DirectoryMatch> <Files> <FilesMatch> <If> <IfDefine> <IfModule> <IfVersion> <Location> <LocationMatch> <MDomainSet> <Proxy> <ProxyMatch> <VirtualHost> |
有两种基本类型的容器。针对每个请求评估大多数容器。随附的指令仅适用于 match 容器的请求。另一方面,<IfDefine>,<IfModule>和<IfVersion>容器仅在服务器启动和重新启动时进行评估。如果他们的条件在启动时是 true,那么所附的指令将适用于所有请求。如果条件不是 true,则将忽略所附的指令。
<IfDefine>指令包含只有在httpd命令 line 上定义了适当参数时才会应用的指令。例如,使用以下 configuration,只有在使用httpd -DClosedForNow
启动服务器时,所有请求才会重定向到另一个站点:
<IfDefine ClosedForNow> Redirect "/" "http://otherserver.example.com/" </IfDefine>
<IfModule>指令非常相似,除了它包含只有在服务器中有特定模块时才会应用的指令。该模块必须在服务器中静态编译,或者必须动态编译,并且LoadModule line 必须在 configuration 文件中更早。只有在需要 configuration 文件才能使用该命令时,才能使用该指令,无论是否安装了某些模块。它不应该用于包含您希望在整个 time 工作的指令,因为它可以抑制有关丢失模块的有用错误消息。
在以下 example 中,仅当mod_mime_magic可用时才会应用MimeMagicFile指令。
<IfModule mod_mime_magic.c> MimeMagicFile "conf/magic" </IfModule>
<IfVersion>指令与<IfDefine>和<IfModule>非常相似,除了它包含仅在服务器的特定 version 执行时才应用的指令。该模块设计用于测试套件和大型网络,这些网络必须处理不同的 httpd 版本和不同的配置。
<IfVersion >= 2.4> # this happens only in versions greater or # equal 2.4.0. </IfVersion>
<IfDefine>,<IfModule>和<IfVersion>可以通过在测试前加上“!”来应用负条件。此外,这些部分可以嵌套以实现更复杂的限制。
Filesystem,Webspace 和 Boolean Expressions
最常用的 configuration 节容器是更改文件系统或网站空间中特定位置的 configuration 的容器。首先,了解两者之间的区别非常重要。文件系统是操作系统可以看到的磁盘视图。例如,在默认安装中,Apache httpd 驻留在 Unix 文件系统中的/usr/local/apache2
或 Windows 文件系统中的"c:/Program Files/Apache Group/Apache2"
。(请注意,正斜杠应始终用作 Apache 的 httpd configuration files 路径分隔符,即使是 Windows.)相比之下,网络空间是网站由 Web 服务器交付,由 client 看到的视图,因此该路径/dir/
在 webspace 对应于 Unix 上默认 Apache httpd 安装的文件系统中的路径/usr/local/apache2/htdocs/dir/
。网站空间不需要直接 map 到文件系统,因为网页可以从数据库或其他位置动态生成。
Filesystem Containers
<Directory>和<Files>指令及其正则表达式副指令将指令应用于文件系统的某些部分。包含在<Directory>部分中的指令适用于指定的文件系统目录和该目录的所有子目录(以及这些目录中的 files)。使用.htaccess files可以获得相同的效果。例如,在以下 configuration 中,将为/var/web/dir1
目录和所有子目录启用目录索引。
<Directory "/var/web/dir1"> Options +Indexes </Directory>
包含在<Files>部分中的指令适用于具有指定 name 的任何文件,无论它位于何种目录中。因此,对于 example,以下 configuration 指令将放置在 configuration 文件的主要部分中,拒绝访问任何名为的文件private.html
无论在哪里找到它。
<Files "private"> Require all denied </Files>
要解决在文件系统的特定部分中找到的 files,可以组合<Files>和<Directory>部分。例如,以下 configuration 将拒绝访问/var/web/dir1/private.html
目录下的/var/web/dir1/private.html
,/var/web/dir1/subdir2/private.html
,/var/web/dir1/subdir3/private.html
和private.html
的任何其他实例。
<Directory "/var/web/dir1"> <Files "private"> Require all denied </Files> </Directory>
Webspace 容器
另一方面,<Location>指令及其正则表达式对应方改变了网站空间中内容的 configuration。例如,以下 configuration 阻止访问以/private 开头的任何 URL-path。特别是,它将应用于http://yoursite.example.com/private
,http://yoursite.example.com/private123
和http://yoursite.example.com/private/dir/file.html
的请求以及以/private
string 开头的任何其他请求。
<LocationMatch "^/private"> Require all denied </LocationMatch>
<Location>指令不需要与文件系统有任何关系。对于 example,以下 example 显示了如何将特定 URL map 映射到mod_status提供的内部 Apache HTTP Server 处理程序。文件系统中不需要存在名为server-status
的文件。
<Location "/server-status"> SetHandler server-status </Location>
重叠网站空间
在 order 中有两个重叠的 URL,必须考虑评估某些部分或指令的 order。对于<Location>,这将是:
<Location "/foo"> </Location> <Location "/foo/bar"> </Location>
另一方面,<Alias> es 被映射 vice-versa:
Alias "/foo/bar" "/srv/www/uncommon/bar" Alias "/foo" "/srv/www/common/foo"
对于ProxyPass指令,true 也是如此:
ProxyPass "/special-area" "http://special.example.com" smax=5 max=10 ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On
通配符和正则表达式
<Directory>,<Files>和<Location>指令都可以使用 shell-style 通配符,如 C 标准 library 中的fnmatch
。字符“*”匹配任何字符序列,“?”匹配任何单个字符,“[161]”匹配 seq 中的任何字符。“/”字符不会被任何通配符匹配;必须明确指定。
如果需要更灵活的匹配,每个容器都有一个正则表达式(正则表达式)对应<DirectoryMatch>,<FilesMatch>和<LocationMatch>,允许 perl-compatible 常用表达用于选择匹配。但请参阅下面有关 configuration 合并的部分,以了解使用正则表达式部分将如何更改指令的应用方式。
更改所有用户目录的 configuration 的 non-regex 通配符部分可能如下所示:
<Directory "/home/*/public_html"> Options Indexes </Directory>
使用正则表达式部分,我们可以一次拒绝访问多种类型的图像 files:
<FilesMatch "\.(?i:gif|jpe?g|png)$"> Require all denied </FilesMatch>
包含命名组和反向引用的正则表达式将添加到环境中,并且相应的 name 为大写。这允许在表达式和modrewrite之类的模块中引用文件名_path 和 URL 的元素。
<DirectoryMatch "^/var/www/combined/(?<SITENAME>[^/]+)"> require ldap-group "cn=%{env:MATCH_SITENAME},ou=combined,o=Example" </DirectoryMatch>
Boolean 表达式
<If>指令根据可由 boolean 表达式表示的条件更改 configuration。例如,如果 HTTP Referer 标头不以“http://www.example.com/”开头,则以下 configuration 拒绝访问。
<If "!(%{HTTP_REFERER} -strmatch 'http://www.example.com/*')"> Require all denied </If>
使用什么时候
在文件系统容器和 webspace 容器之间进行选择实际上非常简单。将指令应用于驻留在文件系统中的 object 时,始终使用<Directory>或<Files>。将指令应用于不驻留在文件系统中的 objects(例如从数据库生成的网页)时,请使用<Location>。
在尝试限制对文件系统中的 objects 的访问时,永远不要使用<Location>。这是因为许多不同的网站空间位置(URL)可以 map 到同一个文件系统位置,从而可以规避您的限制。对于 example,请考虑以下 configuration:
<Location "/dir/"> Require all denied </Location>
如果请求是http://yoursite.example.com/dir/
,这可以正常工作。但是如果你在 case-insensitive 文件系统上呢?然后,通过请求http://yoursite.example.com/DIR/
可以轻松规避您的限制。相反,<Directory>指令将适用于从该位置提供的任何内容,无论其如何调用。(exception 是文件系统链接。可以使用符号链接将相同的目录放在文件系统的多个部分中.<Directory>指令将遵循符号链接而不重置路径名。因此,对于最高级别的安全性,符号链接应该使用适当的选项 directive.)禁用
如果你是因为使用 case-sensitive 文件系统而认为这一点适用于你,请记住,还有很多其他方法可以将多个网站空间位置映射到同一个文件系统位置。因此,您应该始终使用文件系统容器。但是,这条规则有一个例外。将 configuration 限制放在<Location "/">
部分是完全安全的,因为无论具体的 URL 如何,此部分都将应用于所有请求。
部分嵌套
某些节类型可以嵌套在其他节类型中。一方面,<Files>可以在<Directory>中使用。另一方面,<If>可以在<Directory>,<Location>和<Files>部分内使用(但不能在另一个<If>内部)。命名部分的正则表达式对应物的行为相同。
嵌套的部分在相同类型的 non-nested 部分之后合并。
虚拟主机
<VirtualHost>容器包含适用于特定主机的指令。当从同一台计算机为多个主机提供服务时,这对于每个主机具有不同的 configuration 非常有用。有关更多信息,请参阅虚拟 Host 文档。
代理
<Proxy>和<ProxyMatch>容器仅将封闭的 configuration 指令应用于通过mod_proxy代理服务器访问的网站匹配指定的 URL。例如,以下 configuration 将仅允许 clients 的一个子集使用代理服务器访问www.example.com
网站:
<Proxy "http://www.example.com/*"> Require host yournetwork.example.com </Proxy>
允许哪些指令?
要找出哪些类型的 configuration 部分允许哪些指令,请检查指令的Context。<Directory>节中允许的所有内容在语法上也允许在<DirectoryMatch>,<Files>,<FilesMatch>,<Location>,<LocationMatch>,<Proxy>和<ProxyMatch>节中。但是有一些 exceptions:
- AllowOverride指令仅适用于<Directory>节。
FollowSymLinks
和SymLinksIfOwnerMatch
选项仅在<Directory>部分或.htaccess
files 中起作用。- 选项指令不能在<Files>和<FilesMatch>部分中使用。
如何合并这些部分
configuration 部分应用于一个非常特殊的 order。由于这会对 configuration 指令的解释方式产生重要影响,因此了解其工作原理非常重要。
合并的顺序是:
- <Directory>(正则表达式除外)和
.htaccess
同时完成(使用.htaccess
,如果允许,覆盖<Directory>) - <DirectoryMatch>(和
<Directory "~">
) - <Files>和<FilesMatch>同时完成
- <Location>和<LocationMatch>同时完成
- <If>
一些重要的评论:
- 除了<Directory>之外,在每个 group 中,这些部分都在它们出现在 configuration files 中的 order 中处理。例如,对/foo/bar 的请求将 match
<Location "/foo/bar">
和<Location "/foo">
(在这种情况下为 group 4):将评估这两个部分,但在 order 中它们出现在 configuration files 中。 - <Directory>(上面的 group 1)在 order 最短目录 component 中处理为最长。对于 example,
<Directory "/var/web/dir">
将在<Directory "/var/web/dir/subdir">
之前处理。 - 如果多个<Directory>部分应用于同一目录,则会在 configuration 文件 order 中处理它们。
- 通过包括指令包含的配置将被视为它们位于包括指令位置的包含文件中。
- <VirtualHost>部分内的部分应用于虚拟 host 定义之外的相应部分之后。这允许虚拟主机覆盖主服务器 configuration。
- 当请求由mod_proxy提供时,<Proxy>容器取代处理 order 中的<Directory>容器。
技术说明
实际上在 name 转换阶段之前执行了<Location>
/<LocationMatch>
序列(其中Aliases
和DocumentRoots
用于将 URL 映射到文件名)。翻译完成后,该序列的结果将完全丢弃。
模块和 configuration 部分之间的关系
在阅读 configuration 部分如何合并之后经常出现的一个问题与如何以及何时处理特定模块(如modrewrite)的指令有关。答案并非微不足道,需要一些背景知识。每个 httpd 模块管理自己的 configuration,httpd.conf 中的每个指令在特定的 context 中指定一个 configuration。 httpd 在读取时不执行命令。
在运行时,httpd 的核心遍历上述 order 中定义的 configuration 部分,以确定哪些部分适用于当前请求。当第一部分匹配时,它被视为此请求的当前配置。如果后续部分也匹配,那么在任一部分中具有指令的每个模块都有机会在两个部分之间合并其 configuration。结果是第三个 configuration,process 继续,直到评估所有 configuration 部分。
在上述 step 之后,HTTP 请求的“真实”处理开始:每个模块都有机会运行并执行他们喜欢的任何任务。他们可以从 httpd 的核心检索自己的最终合并 configuration,以确定它们应该如何操作。
example 可以帮助可视化整个 process。以下 configuration 使用modheaders的头指令来设置特定的 HTTP 标头。对于/example/index.html
的请求,httpd 在CustomHeaderName
标头中设置的 value 是什么?
<Directory "/"> Header set CustomHeaderName one <FilesMatch ".*"> Header set CustomHeaderName three </FilesMatch> </Directory> <Directory "/example"> Header set CustomHeaderName two </Directory>
Directory
“/”匹配并创建初始 configuration 以设置带有 valueone
的CustomHeaderName
标头。Directory
“/example”匹配,并且由于modheaders在其 code 中指定在合并的情况下覆盖,因此创建新的 configuration 以使用 valuetwo
设置CustomHeaderName
标头。FilesMatch
“.*”匹配并出现另一个合并机会,导致使用 valuethree
设置CustomHeaderName
标头。- 最终,在 HTTP 请求处理的后续步骤中,将调用modheaders,它将接收 configuration 以使用 value
three
设置CustomHeaderName
标头。 modheaders通常使用此 configuration 来执行其 job,即设置 foo 标头。这并不意味着模块不能执行更复杂的操作,例如丢弃指令,因为不需要或弃用等等。
这也是.htaccess 的 true,因为它们与 merge order 中的Directory
具有相同的优先级。要理解的重要概念是Directory
和FilesMatch
之类的配置部分与头或重写规则之类的模块特定指令不具有可比性,因为它们在不同的级别上运行。
一些有用的例子
下面是一个人工示例来显示合并的 order。假设它们都适用于请求,则此 example 中的指令将应用于 order A> B> C> D> E.
<Location "/"> E </Location> <Files "f"> D </Files> <VirtualHost *> <Directory "/a/b"> B </Directory> </VirtualHost> <DirectoryMatch "^.*b$"> C </DirectoryMatch> <Directory "/a/b"> A </Directory>
有关更具体的示例,请考虑以下事项。无论<Directory>部分中是否存在任何访问限制,<Location>部分都将在最后评估,并允许不受限制地访问服务器。换句话说,合并顺序很重要,所以要小心!
<Location "/"> Require all granted </Location> # Whoops! This <Directory> section will have no effect <Directory "/"> <RequireAll> Require all granted Require not host badguy.example.com </RequireAll> </Directory>