从身份验证中排除目录后,Apache 重写规则不起作用

从身份验证中排除目录后,Apache 重写规则不起作用

我希望目录“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选项。)

相关内容