Apache - 自定义错误页面仅对文件请求返回错误 AH01071

Apache - 自定义错误页面仅对文件请求返回错误 AH01071

我有一个由共享托管提供商托管的网站。它是带有 FPM/FastCGI 和 PHP 7.2 的 Apache

作为共享主机,我可以访问的唯一配置是 htaccess,但显然不是任何 Apache conf 文件。

我在 htaccess 中配置了一个自定义错误页面,如下所示:ErrorDocument 404 /error404.php。今天我注意到我的自定义错误 404 页面没有显示。相反,File not found.浏览器会返回纯文本,并在标头中显示状态代码 404。进一步调查显示,这种情况仅发生在请求文件。如果您请求不存在的目录然后你就会得到自定义错误页面!例如,请求mydomain.info/dummy.htm给出错误,但请求mydomain.info/dummy/返回自定义错误页面。

服务器正在记录每个错误AH01071的错误。Primary script unknownFile not found.

看来服务器上启用了 ModSecurity,因为日志记录了恶意请求被拒绝,例如[client xxx.xxx.xxx.xxx] ModSecurity: Access denied with code 403 (phase 2). ... etc

另外,我最近按照托管服务提供商的建议改用了 PHP 7.2。但改回 5.6 并没有改变症状。

知道是什么原因造成的吗?我看到过一些信息,说也许ProxyPass或者ProxyErrorOverride可以解决问题,但我不知道在哪里设置。

为了记录,下面是完整的 htaccess,包括所有缺陷:

RewriteEngine on

# AddType TYPE/SUBTYPE EXTENSION
AddType audio/mpeg mp3
AddType video/mp4 mp4 m4v

# Add WWW
RewriteCond %{HTTP_HOST} ^mydomain\.info [NC]
RewriteRule ^(.*) https://www.mydomain.info/$1 [R=301,L,NE]

# Redirect for .COM
RewriteCond %{HTTP_HOST} mydomain\.com$ [NC]
RewriteRule ^/?(.*) https://www.mydomain.info/$1 [R=301,L,NE]

# Force HTTPS
RewriteEngine On 
RewriteCond %{HTTPS} off 
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]

# Home page canonicalization
RewriteCond %{THE_REQUEST} ^.*\/index\.htm\ HTTP/
RewriteRule ^(.*)index\.htm$ /$1 [R=301,L,NE]

# Removed page_missing.htm
Redirect 301 /page_missing.htm /new_page.htm#section_b

# Some content moved to sub-folder
Redirect 301 /extra_content.htm /extra/extra_content.htm

# Internally redirect all HTM & HTML URLs to PHP
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)\.(htm|html)$ /$1\.php

# Error 404 page
ErrorDocument 404 /error404.php

<IfModule mod_expires.c>
    # Activate mod_expires for this directory
    ExpiresActive on

    # Default
    ExpiresDefault "access plus 7 days"

    # Default for actual documents
    ExpiresByType text/html "access plus 15 minutes"

    # cache CSS files for 7 days
    ExpiresByType text/css "access plus 7 days"

    # locally cache common resource types for 7 days
    ExpiresByType image/jpg "access plus 7 days"
    ExpiresByType image/jpeg "access plus 7 days"
    ExpiresByType image/gif "access plus 7 days"
    ExpiresByType image/png "access plus 7 days"
    ExpiresByType application/pdf "access plus 7 days"    
    ExpiresByType audio/mpeg "access plus 7 days"    
</IfModule> 

答案1

# Internally redirect all HTM & HTML URLs to PHP
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)\.(htm|html)$ /$1\.php

我并不一定会期望这会导致您遇到的问题,但是,您有指令“盲目地”将任何不存在的.htm(或.html)请求重写为等效.php文件,无论该.php文件是否存在。 (错误文档应该捕获丢失的文件,而不是最初请求的.php丢失文件。).htm

这也可以解释您在请求不存在的“目录”(即形式的请求)时看到的行为差异/dummy/,该请求不会被上述指令重写并且似乎按预期“工作”(即调用自定义错误文档)。

您可以修改上述规则,以便仅.php在文件存在时才重写。例如:

# Internally redirect all HTM & HTML URLs to PHP
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.*)\.(htm|html)$ /$1.php [L]

无需对文字点进行转义RewriteRule 代换。您应该包含该L标志(尽管它目前是最后一个 mod_rewrite 指令,因此严格来说并不重要)。


更新:如果您请求不存在的 php 页面,那么您仍然会收到“找不到文件”的响应。

这听起来像是服务器配置问题。您可以通过手动重写错误文档来“解决”此问题:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.php$ /error404.php [L]

尽管您可能需要进行修改error404.php来解决这个问题。

或者... 我还想知道从 Apache 触发 404(从表面上看,这似乎没有太大意义)是否会改变此行为。例如,代替上面的重写:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.php$ - [R=404]

这种方法背后的想法是,它有望引发内部子请求在将请求传递给 PHP 处理程序之前,对错误文档进行检查(这似乎与错误文档相冲突)。然后,PHP 处理程序只会被调用来提供错误文档。

相关内容