Apache以404而不是403响应,忽略F标志
我有一个简单的项目层次结构: 位于Apache以404而不是403响应,忽略F标志,apache,.htaccess,mod-rewrite,Apache,.htaccess,Mod Rewrite,我有一个简单的项目层次结构: 位于/www根文件夹的.htaccess文件的内容包括: RewriteEngine On RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} "\.php$" RewriteRule .* - [F] 当请求任何.php文件但index.php时,.htaccess中的规则应返回403。php模板的内容不相关 如果我没有错,如果请求的最后一部分是现有.php文件的
/www
根文件夹的.htaccess
文件的内容包括:
RewriteEngine On
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} "\.php$"
RewriteRule .* - [F]
当请求任何.php文件但index.php
时,.htaccess
中的规则应返回403。php模板的内容不相关
如果我没有错,如果请求的最后一部分是现有.php文件的名称,并且重写引擎处于启用状态,则无论您是否指定.php部分,Apache都会为其提供服务。在我的例子中,如果我注释掉.htaccess
的最后两行,则以下任何URL:
localhost/pages/page
localhost/pages/page/
返回/pages/page.php的内容
我的问题是,鉴于上述.htaccess
,如果我编写此url:
localhost/pages/page.php
我得到了预期的403。但如果我写下以下任何一项:
localhost/pages/page
localhost/pages/page/
我得到了一个404(未找到),而不是预期的403。为什么我会得到404呢?很有趣。。。我可以在Apache2.4上重现这种行为,但无法解释它-在我看来这像是一个bug,因为用R=403
替换F
会产生所需的结果(应该没有区别)-见下文
为了澄清,要将/pages/page
解析为/pages/page.php
首先取决于启用的多视图
(如注释中所述)。或者,您可以使用mod_rewrite来实现这一点,但这里没有证据证明这一点。Apache上默认情况下禁用多视图,但某些共享主机出于某种原因启用了多视图(这使无扩展URL“正常工作”)。但是,多视图是与mod_rewrite发生意外冲突的常见原因。无扩展URL“只是(意外地)工作”这一事实可能会导致规范化方面的其他问题
我认为存在“bug”的原因是,如果您简单地将F
标志更改为R=403
,那么您确实会得到“预期的”403响应:
F
和R=403
之间应该没有区别。好吧,F
只是一条捷径
我尝试了选项-多视图
,但得到了相同的结果
但是,禁用多视图时,404是预期的响应
禁用多视图后,如果您请求/pages/page
,请求文件名
的格式将为/abs/path/to/pages/page
(无.php
扩展名)。您的条件不匹配,因此请求通过404
您最好使用禁用的多视图。对于/pages/page
和/pages/page/
来说,“神奇地”解析为/pages/page.php
,这是不“正常的”。在这种情况下,/pages/page
和/pages/page/
导致404是“正常”的。如果您使用mod_rewrite做了很多工作,请求的URL映射到文件系统,那么您可能会遇到冲突
请注意,多视图不仅仅适用于.php
文件。启用多视图后,您将拥有无扩展的一切。图像、脚本、HTML、样式表等。如果您有多个具有公共基名称和mime类型的文件,将提供哪些服务?例如foo.php
或foo.html
当然,您可以创建mod_rewrite指令来启用此行为,但这不是自动的
更新:一个更简洁的示例
给定一个文件/page.php
(在文档根目录中)并启用多视图。
(例如,选项+多视图
)
请求/page
(或/page/
)会导致多视图/mod_协商服务/page.php
而不是内部子请求
现在,让我们用mod_rewrite阻止所有访问,并提供403禁止:
RewriteRule ^ - [F]
这将用403阻止每个请求。但是,请求/page
或/page/
(一个由多视图成功重写的URL)会导致404 Not Found响应
但是,将上述规则更改为使用R
标志:
RewriteRule ^ - [R=403]
现在,所有内容都返回403,包括上面提到的两个URL!但是F
和R=403
应该会导致相同的行为。“如果请求的最后一部分是现有.php文件的名称,并且重写引擎处于启用状态,则无论您是否指定.php部分,Apache都会为其提供服务。”-这不是mod_rewrite的做法,这是多视图的效果。我的猜测是,它可能在这里也会干扰,所以请尝试使用选项-MultiViews
@CBroe禁用它。我曾尝试使用选项-MultiViews
,但如果不启用MultiViews,我会得到相同的结果,我不明白/www/pages/page
或/www/pages/page/
如何让它首先找到/www/pages/page.php
。请求文件名
此时还不一定解析为实际的物理文件名,因此它可能仍然包含与请求URI
相同的内容。因此,对于/www/pages/page/
,通过在现有文件末尾附加.php
来测试该文件将不起作用。@CBrow我认为启用该行为的模块(我猜是内容协商模块?)在本地主机Apache安装中默认启用。无论如何,我已经尝试将301重定向到index.php,并将REQUEST\u FILENAME
附加为querystring参数:RewriteRule。index.php?q=%{REQUEST_FILENAME}[R=301,L]
并以实际文件路径响应:https://localhost/index.php?q=D:/wamp64/www/pages/page.php
当我输入url时https://localhost/pages/page
那么,是否应该以某种方式报告此问题?您正在运行什么版本的Apache,在什么平台上运行?诚然,我正在Apache2.4.7的一个相当旧的版本(在W
RewriteRule ^ - [R=403]