On this page
Configuration Sections
configuration files中的指令可能适用于整个服务器,或者可能仅限于特定目录,文件,主机或 URL。本文档介绍了如何使用配置节容器或.htaccess
文件来更改其他配置指令的范围。
配置节容器的类型
容器有两种基本类型。每个请求都会评估大多数容器。随附的指令仅适用于与容器匹配的那些请求。另一方面,仅在服务器启动和重新启动时评估<IfDefine>,<IfModule>和<IfVersion>容器。如果启动时它们的条件为真,则随附的指令将适用于所有请求。如果条件不成立,将忽略附带的指令。
<IfDefine>指令包含仅在httpd命令行上定义了适当参数时才会应用的指令。例如,使用以下配置,仅当使用httpd -DClosedForNow
启动服务器时,所有请求才会重定向到另一个站点:
<IfDefine ClosedForNow>
Redirect "/" "http://otherserver.example.com/"
</IfDefine>
<IfModule>指令非常相似,除了它包含仅在服务器中有特定模块可用时才应用的指令。该模块必须在服务器中静态编译,或者必须动态编译,并且其LoadModule行必须在配置文件中更早。仅在您需要配置文件才能工作(无论是否安装了某些模块)时,才应使用此伪指令。不应将其用于始终包含要使用的指令,因为它可以抑制有关缺少模块的有用错误消息。
在以下示例中,仅当mod_mime_magic可用时才应用MimeMagicFile伪指令。
<IfModule mod_mime_magic.c>
MimeMagicFile "conf/magic"
</IfModule>
<IfVersion>指令与<IfDefine>和<IfModule>非常相似,除了它包含仅在执行特定版本的服务器时才应用的指令。该模块设计用于在测试套件和大型网络中使用,这些套件必须处理不同的 httpd 版本和不同的配置。
<IfVersion >= 2.4>
# this happens only in versions greater or
# equal 2.4.0.
</IfVersion>
<IfDefine>,<IfModule>和<IfVersion>可以通过在测试前加“!”来应用否定条件。同样,可以嵌套这些部分以实现更复杂的限制。
文件系统,网站空间和布尔表达式
最常用的配置节容器是那些更改文件系统或 Web 空间中特定位置的配置的容器。首先,重要的是要了解两者之间的区别。文件系统是 os 所看到的磁盘视图。例如,在默认安装中,Apache httpd 位于 Unix 文件系统中的/usr/local/apache2
或 Windows 文件系统中的"c:/Program Files/Apache Group/Apache2"
。 (请注意,即使在 Windows 中,正斜杠也应始终用作 Apache httpd 配置文件中的路径分隔符,即使对于 Windows 也是如此.)相比之下,Webspace 是 Web 服务器交付并由 Client 端看到的站点视图。因此,Web 空间中的路径/dir/
对应于 Unix 上默认 Apache httpd 安装的文件系统中的路径/usr/local/apache2/htdocs/dir/
。 Web 空间不必直接 Map 到文件系统,因为可以从数据库或其他位置动态生成网页。
Filesystem Containers
<Directory>和<Files>伪指令以及regex伪指令将伪指令应用于文件系统的各个部分。 <Directory>部分中包含的指令适用于命名的文件系统目录以及该目录的所有子目录(以及那些目录中的文件)。使用.htaccess files可以获得相同的效果。例如,在以下配置中,将为/var/web/dir1
目录及其所有子目录启用目录索引。
<Directory "/var/web/dir1">
Options +Indexes
</Directory>
<Files>部分中包含的指令适用于具有指定名称的任何文件,而不管其位于哪个目录。因此,例如,以下配置指令将放在配置文件的主要部分时,拒绝访问任何名为private.html
,无论在哪里找到它。
<Files "private.html">
Require all denied
</Files>
要处理在文件系统特定部分中找到的文件,可以将<Files>和<Directory>部分组合在一起。例如,以下配置将拒绝访问/var/web/dir1/private.html
,/var/web/dir1/subdir2/private.html
,/var/web/dir1/subdir3/private.html
以及在/var/web/dir1/
目录下找到的private.html
的任何其他实例。
<Directory "/var/web/dir1">
<Files "private.html">
Require all denied
</Files>
</Directory>
Webspace Containers
另一方面,<Location>指令及其对应的regex更改了 Web 空间中内容的配置。例如,以下配置阻止访问任何以/ private 开头的 URL 路径。特别是,它将适用于对http://yoursite.example.com/private
,http://yoursite.example.com/private123
和http://yoursite.example.com/private/dir/file.html
的请求以及以/private
字符串开头的任何其他请求。
<LocationMatch "^/private">
Require all denied
</LocationMatch>
<Location>指令与文件系统没有任何关系。例如,以下示例显示如何将特定的 URL Map 到mod_status提供的内部 Apache HTTP Server 处理程序。文件系统中无需存在名为server-status
的文件。
<Location "/server-status">
SetHandler server-status
</Location>
Overlapping Webspace
为了具有两个重叠的 URL,必须考虑某些节或指令的评估 Sequences。对于<Location>,这将是:
<Location "/foo">
</Location>
<Location "/foo/bar">
</Location>
另一方面,<Alias>是 Map 的,反之亦然:
Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo" "/srv/www/common/foo"
ProxyPass指令也是如此:
ProxyPass "/special-area" "http://special.example.com" smax=5 max=10
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On
通配符和正则表达式
<Directory>,<Files>和<Location>伪指令可以分别使用 C 标准库中fnmatch
一样的 shell 样式通配符。字符“ ”与任何字符序列“?”匹配匹配任何单个字符,而“ [* * seq *]”匹配 seq *中的任何字符。 “ /”字符不会与任何通配符匹配;必须明确指定。
如果需要更加灵活的匹配,则每个容器都有一个正则表达式(regex)对应项<DirectoryMatch>,<FilesMatch>和<LocationMatch>,这些匹配项允许使用与 perl 兼容的regular expressions来选择匹配项。但是请参阅下面有关配置合并的部分,以了解使用正则表达式的部分将如何更改指令的应用方式。
更改所有用户目录配置的非正则表达式通配符部分如下所示:
<Directory "/home/*/public_html">
Options Indexes
</Directory>
使用正则表达式部分,我们可以一次拒绝访问多种类型的图像文件:
<FilesMatch "\.(?i:gif|jpe?g|png)$">
Require all denied
</FilesMatch>
包含 命名组和反向引用 的正则表达式以大写形式添加到具有相应名称的环境中。这允许从expressions和mod_rewrite之类的模块中引用文件名路径和 URL 的元素。
<DirectoryMatch "^/var/www/combined/(?<SITENAME>[^/]+)">
Require ldap-group "cn=%{env:MATCH_SITENAME},ou=combined,o=Example"
</DirectoryMatch>
Boolean expressions
<If>指令根据可以由布尔表达式表示的条件来更改配置。例如,如果 HTTP Referer Headers 不是以“ http://www.example.com/”开头,则以下配置拒绝访问。
<If "!(%{HTTP_REFERER} -strmatch 'http://www.example.com/*')">
Require all denied
</If>
使用时间
实际上,在文件系统容器和 Webspace 容器之间进行选择非常容易。将指令应用于驻留在文件系统中的对象时,请始终使用<Directory>或<Files>。将指令应用于不在文件系统中的对象(例如从数据库生成的网页)时,请使用<Location>。
尝试限制对文件系统中对象的访问时,千万不要使用<Location>,这一点很重要。这是因为许多不同的网站空间位置(URL)可以 Map 到同一文件系统位置,从而可以规避您的限制。例如,考虑以下配置:
<Location "/dir/">
Require all denied
</Location>
如果请求是http://yoursite.example.com/dir/
,则此方法很好。但是,如果您使用的是不区分大小写的文件系统,该怎么办?然后,通过请求http://yoursite.example.com/DIR/
可以轻松绕开您的限制。相反,<Directory>指令将应用于从该位置提供的任何内容,而不管其调用方式如何。 (文件系统链接是一个 exception.使用符号链接可以将同一目录放置在文件系统的多个部分中.<Directory>指令将跟随符号链接而不会重置路径名。因此,为了获得最高的安全性,符号链接应通过相应的Options指令被禁用。)
如果您以为使用区分大小写的文件系统,可能认为这都不适合您,请记住,还有许多其他方法可以将多个网站空间位置 Map 到同一文件系统位置。因此,您应该始终尽可能使用文件系统容器。但是,此规则有一个 exception。将配置限制放在<Location "/">
节中是绝对安全的,因为此节将适用于所有请求,而不管特定的 URL。
部分的嵌套
某些节类型可以嵌套在其他节类型中。一方面,可以在<Directory>内部使用<Files>。另一方面,可以在<Directory>,<Location>和<Files>部分内部使用<If>(但不能在另一个<If>内部使用)。命名部分的正则表达式对应的行为相同。
嵌套部分在相同类型的非嵌套部分之后合并。
Virtual Hosts
<VirtualHost>容器包含适用于特定主机的指令。当从同一台计算机为多台主机提供不同配置时,这很有用。有关更多信息,请参见虚拟主机文档。
Proxy
<Proxy>和<ProxyMatch>容器仅将随附的配置指令应用于通过mod_proxy的代理服务器访问的,与指定 URL 匹配的站点。例如,以下配置将仅允许一部分 Client 端使用代理服务器访问www.example.com
网站:
<Proxy "http://www.example.com/*">
Require host yournetwork.example.com
</Proxy>
允许哪些指令?
要找出在哪些类型的配置节中允许使用哪些指令,请检查指令的Context。句法上<DirectoryMatch>,<Files>,<FilesMatch>,<Location>,<LocationMatch>,<Proxy>和<ProxyMatch>部分中也允许<Directory>部分中允许的所有内容。但是,有一些 exception:
AllowOverride指令仅在<Directory>部分中有效。
FollowSymLinks
和SymLinksIfOwnerMatch
Options仅在<Directory>节或.htaccess
文件中起作用。Options伪指令不能在<Files>和<FilesMatch>部分中使用。
各部分的合并方式
配置部分以非常特殊的 Sequences 应用。由于这会对配置指令的解释方式产生重要影响,因此了解其工作原理非常重要。
合并 Sequences 为:
<Directory>(正则表达式除外)和
.htaccess
同时完成(使用.htaccess
,如果允许,则覆盖<Directory>)<DirectoryMatch>(和
<Directory "~">
)<Files>和<FilesMatch>同时完成
一些重要的 Comment:
除了<Directory>之外,每个组中的节均按照它们在配置文件中出现的 Sequences 进行处理。例如,对*/foo/bar *的请求将匹配
<Location "/foo/bar">
和<Location "/foo">
(在本例中为第 4 组):将评估两个部分,但 Sequences 将出现在配置文件中。<Directory>(上述第 1 组)以 Sequences 最短的目录组件中最长的 Sequences 进行处理。例如,
<Directory "/var/web/dir">
将在<Directory "/var/web/dir/subdir">
之前处理。如果多个<Directory>节应用于同一目录,则会按配置文件 Sequences 对其进行处理。
<VirtualHost>部分中的部分在虚拟主机定义之外的相应部分之后*被应用。这允许虚拟主机覆盖主服务器配置。
当mod_proxy处理请求时,<Proxy>容器在处理 Sequences 中代替<Directory>容器。
Technical Note
实际上,在名称转换阶段之前实际上执行了一个<Location>
/<LocationMatch>
序列(其中Aliases
和DocumentRoots
用于将 URL Map 到文件名)。翻译完成后,此序列的结果将被完全丢弃。
模块与配置部分之间的关系
在阅读如何合并配置节之后,经常会出现一个问题,该问题与如何和何时处理诸如mod_rewrite之类的特定模块的指令有关。答案并不简单,需要一些背景知识。每个 httpd 模块 Management 自己的配置,并且 httpd.conf 中的每个指令都在特定上下文中指定一个配置。 httpd 在读取时不执行命令。
在运行时,httpd 的核心按照上述 Sequences 遍历已定义的配置节,以确定哪些节适用于当前请求。当第一部分匹配时,它将被视为此请求的当前配置。如果后续部分也匹配,则每个部分中带有指令的每个模块都有机会在两个部分之间合并其配置。结果是第三个配置,该过程一直进行到评估所有配置部分为止。
完成上述步骤后,HTTP 请求的“实际”处理开始:每个模块都有机会运行并执行所需的任何任务。他们可以从 httpd 的核心中检索自己最终的合并配置,以确定应如何操作。
一个示例可以帮助可视化整个过程。以下配置使用mod_headers的Header伪指令设置特定的 HTTP Headers。对于/example/index.html
请求,httpd 将在CustomHeaderName
Headers 中设置什么值?
<Directory "/">
Header set CustomHeaderName one
<FilesMatch ".*">
Header set CustomHeaderName three
</FilesMatch>
</Directory>
<Directory "/example">
Header set CustomHeaderName two
</Directory>
Directory
“ /”匹配,并创建初始配置以将CustomHeaderName
Headers 设置为值one
。Directory
“/example”匹配,并且由于mod_headers在其代码中指定在合并的情况下要覆盖,因此将创建新配置以将CustomHeaderName
Headers 设置为值two
。FilesMatch
“.*”匹配并且出现另一个合并机会,导致CustomHeaderName
Headers 设置为值three
。最终,在 HTTP 请求处理的后续步骤中,将调用mod_headers,它将接收将
CustomHeaderName
Headers 设置为值three
的配置。 mod_headers通常使用此配置执行其工作,即设置 foo Headers。这并不意味着模块无法执行更复杂的操作,例如丢弃指令,因为不需要或不赞成使用该指令等。
.htaccess 也是如此,因为它们在合并 Sequences 中具有与Directory
相同的优先级。要理解的重要概念是,诸如Directory
和FilesMatch
之类的配置节不能与诸如Header或RewriteRule之类的模块特定指令相提并论,因为它们在不同的级别上运行。
一些有用的例子
以下是显示合并 Sequences 的人工示例。假设它们都适用于请求,则本示例中的指令将按 A> B> C> D> E 的 Sequences 应用。
<Location "/">
E
</Location>
<Files "f.html">
D
</Files>
<VirtualHost *>
<Directory "/a/b">
B
</Directory>
</VirtualHost>
<DirectoryMatch "^.*b$">
C
</DirectoryMatch>
<Directory "/a/b">
A
</Directory>
有关更具体的示例,请考虑以下内容。无论<Directory>部分中有任何访问限制,都将最后评估<Location>部分,并将允许对服务器的无限制访问。换句话说,合并的 Sequences 很重要,所以要小心!
<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>