Apache HTTP服务器 2.0版本
配置文件中的指令的作用域可能是整个服务器,也可能是特定的目录、文件和URL。本文阐述如何使用配置段容器以及.htaccess
文件来改变配置指令的作用域。
相关模块 | 相关指令 |
---|---|
容器有两种基本类型。大多数容器是针对各个请求的,包含于其中的指令仅对与容器匹配的请求起作用,而容器<IfDefine>
和<IfModule>
仅在启动和重新启动中起作用,如果条件成立,则其中的指令有效,否则会被忽略。
<IfDefine>
容器中的指令只有在httpd
命令行中设定了适当的参数后才有效。下例中,只有在服务器用httpd -DClosedForNow
方式启动时,所有的请求才会被重定向到另一个站点。
<IfDefine ClosedForNow>
Redirect / http://otherserver.example.com/
</IfDefine>
<IfModule>
容器很相似,但是其中的指令只有当服务器中存在特定的模块时有效,或者是被静态地编译进了服务器,或者是被动态装载进了服务器,而且,配置文件中其装载指令行LoadModule
必须在出现在此容器之前。这个容器应该仅用于你希望无论特定模块装了还是没装,配置文件都能正常运转的场合;而不应该用于容器中的指令在任何情况下都必须生效的场合,因为它会抑制类似模块没找到的有用的出错信息。
下例中,MimeMagicFiles
指令仅当mod_mime_magic
模块存在时才有效。
<IfModule mod_mime_magic.c>
MimeMagicFile conf/magic
</IfModule>
<IfDefine>
和<IfModule>
都可以在条件前加"!"以实现条件的否定,而且都可以嵌套以实现更复杂的限制。
改变一个在文件系统和网络空间的位置的配置段是最常用的。首先必须理解这两个概念的区别,文件系统是在操作系统中所看见的磁盘上的分布,比如,在Unix文件系统中,Apache会被默认地安装到/usr/local/apache2
,在Windows文件系统中,会装到"c:/Program Files/Apache Group/Apache2"
(注意:Apache始终用斜杠而不是反斜杠作为路径的分隔符,即使是在Windows中)。相反,网络空间是客户在浏览器中所看见的站点上的分布,所以网络空间中的路径 /dir/
对应于Apache在Unix文件系统中的默认安装路径 /usr/local/apache2/htdocs/dir/
。由于网页可以从数据库或其他地方动态生成,因此,网络空间无须直接映射到文件系统。
<Directory>
和<Files>
是针对文件系统的指令。<Directory>
段中的指令作用于指定的文件系统目录及其所有子目录,.htaccess 文件可以达到同样的效果。下例中,/var/web/dir1
及其所有子目录被允许目录列表。
<Directory /var/web/dir1>
Options +Indexes
</Directory>
<Files>
段中的指令作用于特定的文件名,而无论这个文件实际存在于哪个目录。下例中的配置指令如果出现在配置文件的主服务器段,则会拒绝对位于任何目录下的private.html
的访问。
<Files private.html>
Order allow,deny
Deny from all
</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>
Order allow,deny
Deny from all
</Files>
</Directory>
<Location>
是针对网络空间的指令。下例中的配置会拒绝任何对以/private开头的URL的访问,如
http://yoursite.example.com/private
,
http://yoursite.example.com/private123
,
http://yoursite.example.com/private/dir/file.html
等所有以/private
开头的URL。
<Location /private>
Order Allow,Deny
Deny from all
</Location>
<Location>
指令无须文件系统的支持,下例演示了如何映射特定的URL到由mod_status
提供的Apache内部处理器,而并不要求文件系统中确实存在server-status
。
<Location /server-status>
SetHandler server-status
</Location>
<Directory>
,<Files>
, 和<Location>
指令可以使用类似C标准库中的fnmatch
的外壳通配符。符号"*"匹配任何字符串,"?"匹配任何单个的字符,"[seq]" 匹配seq序列中的任何字符,符号"/"不匹配为任何通配符所匹配,所以不能显式使用。
这些指令都有一个正则的配对指令,<DirectoryMatch>
, <FilesMatch>
和<LocationMatch>
,可以使用与perl一致的正则表达式,以提供更复杂的匹配。但是还须注意下文配置的合并中有关使用正则表达式会如何作用于配置指令的内容。
下例使用非正则表达式的通配符来改变所有用户目录的配置:
<Directory /home/*/public_html>
Options Indexes
</Directory>
下例使用正则表达式一次性拒绝对多种图形文件的访问:
<FilesMatch \.(?i:gif|jpe?g|png)$>
Order allow,deny
Deny from all
</FilesMatch>
选择使用文件系统容器还是使用网络空间容器其实很简单。当指令应该作用于文件系统时,总是用<Directory>
或者<Files>
;而当指令作用于不存在于文件系统的对象时,就用<Location>
,比如一个由数据库生成的网页。
不要试图用<Location>
去限制对文件系统中对象的访问,因为许多不同的网络空间路径可能会映射到同一个文件系统目录,导致你的访问限制被突破。比如:
<Location /dir/>
Order allow,deny
Deny from all
</Location>
上述配置对http://yoursite.example.com/dir/
请求的确起作用。但是设想在一个不区分大小写的文件系统中,这个访问限制会被http://yoursite.example.com/DIR/
请求轻易突破。而<Directory>
指令才会真正作用于对这个位置的任何形式的请求。(但是有一个例外,就是Unix文件系统中的连接,符号连接可以使同一个目录出现在文件系统中的多个位置。<Directory>
指令能不经过重置路径名而跟随符号连接,因此,对于安全要求最高的,应该用Options
指令禁止对符号连接的跟随。)
不要认为使用大小写敏感的文件系统就无所谓了,因为有很多方法会将不同的网络空间路径映射为同一个文件系统路径,所以,能使用文件系统容器时就应该使用。但是,也有一个例外,就是,把访问限制放在<Location/>
段中可以很安全地作用于除了某些特定的以外所有的URL。
<VirtualHost>
容器作用于特定的主机,对同一个机器上的具有不同配置的多个主机提供支持。详见:虚拟主机文档(Virtual Host Documentation)。
<Proxy>
和<ProxyMatch>
容器中的指令仅作用于指定URL所匹配的通过mod_proxy
的代理服务器访问的站点。下例中的配置会拒绝通过代理服务器访问cnn.com
站点。
<Proxy http://cnn.com/*>
Order allow,deny
Deny from all
</Proxy>
查阅指令的作用域,就可以知道哪些指令可以出现在哪些段中。从语义上看,允许在<Directory>
段中使用的指令当然也可以在<DirectoryMatch>
,
<Files>
,
<FilesMatch>
,
<Location>
,
<LocationMatch>
,
<Proxy>
和<ProxyMatch>
段中使用,但是有几个例外:
AllowOverride
指令只能出现在<Directory>
段中;Options
中的FollowSymLinks
和
SymLinksIfOwnerMatch
只能出现在<Directory>
段或者.htaccess
文件中;Options
指令不能用于<Files>
和<FilesMatch>
段。配置段会按非常特别的顺序依次生效,由于这会对配置指令的处理结果产生重大影响,理解它的流程尤为重要。
合并的顺序是:
<Directory>
(除了正则表达式)和.htaccess同时处理;(如果允许的话,.htaccess的设置会覆盖<Directory>
的设置)<DirectoryMatch>
(和<Directory ~>
)<Files>
和<FilesMatch>
同时处理;<Location>
和<LocationMatch>
同时处理;除了<Directory>
,每个组都按它们在配置文件中出现的顺序被依次处理,而<Directory>
组,会按字典顺序由短到长被依次处理。例如,<Directory /var/web/dir>
会先于<Directory /var/web/dir/subdir>
被处理。如果有多个指向同一个目录的<Directory>
段,则按它们在配置文件中的顺序被依次处理。用Include
指令包含进来的设置被视为按原样插入到Include
指令的位置。
位于<VirtualHost>
段中的配置段在外部相对应的段处理完毕以后再处理,这样就允许虚拟主机覆盖主服务器的设置。
后面的段覆盖前面的相应的段。
Aliases
和DocumentRoots
来映射URL到文件)之前,会有一个<Location>
/<LocationMatch>
的序列被处理,而在名称翻译结束后,这个序列的处理结果则被完全抛弃。这是一个假设的演示合并顺序的例子。如果这些指令都起作用,则会按A > B > C > D > E的顺序依次生效。
<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>
段将会被最后处理,从而会允许不加限制的对服务器的访问,可见合并的顺序是很重要的,千万小心!
<Location />
Order deny,allow
Allow from all
</Location>
# Woops! This <Directory> section will have no effect
# 哇呀!这个<Directory>段居然不起作用
<Directory />
Order allow,deny
Allow from all
Deny from badguy.example.com
</Directory>