我希望目录“dir”的内容受到保护,但如果用户访问目录本身,我希望改为提供父目录中的 PHP 文件。这适用于以下配置:
<VirtualHost *:80>
LogLevel debug
DocumentRoot "/var/www/html"
ServerName example.com
<Directory /var/www/html>
SetEnvIf Request_URI "dir/$" allow
Order allow,deny
Allow from env=allow
Satisfy any
RewriteEngine on
RewriteRule dir index.php?id=dir [QSA,L]
</Directory>
<Directory /var/www/html/dir>
Require user valid-user
AuthName "Restricted"
AuthType Basic
AuthUserFile /etc/apache2/.htpasswd
#RewriteEngine on
</Directory>
</VirtualHost>
当我访问“example.com/dir”时,会显示 index.php 的内容,当我访问“example.com/dir/file.html”时,我必须先进行身份验证。一切都如我所愿。
但是,当我尝试为其他文件创建 RewriteRules 时,我停止工作。当我在末尾取消注释“#RewriteEngine on”行时,当我尝试访问“example.com/dir”时,出现 404 未找到错误。
为什么会这样?我不需要针对“dir”本身的其他重写规则,但需要针对目录中的某些文件。
答案1
但是,当我尝试为其他文件创建 RewriteRules 时,我停止工作。当我在末尾取消注释“#RewriteEngine on”行时,当我尝试访问“example.com/dir”时,出现 404 未找到错误。
由于 mod_rewrite 指令在默认情况下不会被继承目录上下文。当您在容器RewriteEngine On
中设置时<Directory /var/www/html/dir>
,它会完全覆盖父级中的 mod_rewrite 指令(它们甚至不会运行)。
要按照您编写的方式解决此问题,您需要启用 mod_rewrite 继承。但是,mod_rewrite 指令在“继承”时本质上是就地复制的,并且如果您发布的指令包含在容器中<Directory /var/www/html/dir>
,它将不起作用,因为正则表达式dir
不匹配。
RewriteRule dir index.php?id=dir [QSA,L]
请注意,这不仅仅是重写对目录本身的请求,它还会重写任何仅包含的请求dir
。
为了使其“可继承”(即不依赖于当前目录),请将其更改为:
RewriteCond %{REQUEST_URI} ^/(dir)/?$
RewriteRule ^ /index.php?id=%1 [QSA,L]
并在<Directory /var/www/html/dir>
容器中启用 mod_rewrite 继承。以下任一方式:
RewriteEngine On
# Parent directives are copied AFTER directives in the current scope
RewriteOptions Inherit
或者
# Parent directives are copied BEFORE directives in the current scope
RewriteOptions InheritBefore
(Apache 2.2 才有该inherit
选项。)