由于很久以前的一个错误,我们公司的网站一直在提供包含大量空白的图像 URL。
例如
http://www.example.com/ /assets/ProductPhotos/image.png
浏览器已经以某种方式处理了这个问题(大概是通过删除空白)并且没有人注意到这个问题。
现在我们已经解决了这个问题,但是不那么智能的爬虫程序已经索引了该 URL,并回来尝试再次找到它。
这会导致错误日志中出现一条消息:
[core:error] [pid 5040:tid 1068] (20024)给定的路径格式错误或包含无效字符:[客户端 192.168.128.4:38656] AH00127:无法将 GET /%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20/assets/ProductPhotos/image.png HTTP/1.1 映射到文件
我们看到了很多这样的情况。
Apache 返回一个403 Forbidden
,爬虫程序消失并在几天后再次尝试。
我希望拦截这些请求并返回一个404 Not Found
,甚至一个410 Gone
,或者只是一个,400 Bad Request
希望这样能够说服这些爬虫不要打扰我们。
但是,我还没有找到识别错误 URL 的方法。
目前,我已经
#Trap URLs with occurrences of /<22 spaces>/ and redirect to a 404
<if "%{REQUEST_URI} =~ m#/(%20|\s)+/#">
redirect 404 /
</if>
在我的 .htaccess 文件中,但 Apache 仍然返回403 Forbidden
。就好像 Apache 解析了 URL,判定它是错误的,并返回了响应,所有这些都是在 .htaccess 查看之前完成的。
(我可以将其放在 vHost 文件中,但这需要重新启动实时服务器。这里不流行!)
有没有办法挑选这些坏的 URL 并处理它们,而不依赖于 Apache 的默认行为?
更新:
服务器:Apache 2.4.12,Windows。
我已经设置了一个 virgin vHost,如下所示:
<VirtualHost *:80>
<Directory "c:/***********/websites/webtest">
<RequireAll>
Require all granted
Require ip 192.168.0.0/21 192.168.131.0/24
</RequireAll>
</Directory>
DocumentRoot "c:/*************/websites/webtest"
ServerName webtest.*************
DirectoryIndex index.html
CustomLog "|./bin/rotatelogs.exe -l C:/***********/apache24/logs/webtest.access.%y%m%d.log 86400" combined
ErrorLog "|./bin/rotatelogs.exe -l C:/***********/apache24/logs/webtest.error.%y%m%d.log 86400"
SetEnv WEBSITE_NAME webtest.***********
</VirtualHost>
它有一个文件夹,里面有一些文件,这个文件(与上面相同)的访问文件名在默认部分中ht.conf
被覆盖。引用可以理解为无处不在。.htaccess
.htaccess
ht.conf
#Trap URLs with occurrences of /<22 spaces>/ and redirect to a 404
<if "%{REQUEST_URI} =~ m#/(%20|\s)+/#">
redirect 404 /
</if>
assets/f22.jpg
它还包括相对于文档根目录的文件夹和文件。
浏览http://webtest.**********/assets/f22.jpg
正确返回图像
浏览http://webtest.**********/ /assets/f22.jpg
返回
Forbidden
You don't have permission to access / /assets/f22.jpg on this server.the image correctly
答案1
尝试解决此问题.htaccess
“为时已晚”。正如您所说,这一切都发生在“.htaccess 进入之前”。
.htaccess
文件(和<Directory>
容器)仅被处理后请求已映射到文件系统。如错误消息“无法将...映射到文件”中所述,错误/响应似乎是在请求映射到文件系统时(或之前)触发的。
对于此类请求,“403 Forbidden”响应不是“正常”响应,因此某物似乎强制返回此响应。通常,我期望 Apache 对此类请求返回常规 404。如果 URL 路径完全“无效”,则 Apache 应响应“400 错误请求”(同样,这是无法在 中覆盖的.htaccess
)。
因此,此响应似乎在服务器配置中较早触发。通常,您应该找出 Apache 在哪里/为什么提供此响应。(也许是一个额外的安全模块,如 mod_security?)并相应地修改它,而不是尝试“覆盖”它。但是,由于触发了 403,您可能可以定义自定义 403 ErrorDocument
(同样,在服务器配置中,不是 .htaccess
) 您可以在其中分析请求并相应地进行覆盖。
浏览器已经以某种方式处理了这个问题(大概是通过删除空白)并且没有人注意到这个问题。
“浏览器”不会删除空格。浏览器会(自动)对空格(%20
如果它们没有在 HTML 源代码中明确进行 URL 编码)。据我所知,浏览器端在这方面没有任何变化。
因此,你的服务器之前处理过这些请求,但您的服务器上发生了一些变化,导致这些请求被阻止。或者,事实证明,这些格式错误的 URL 从未起作用,而且没有人注意到丢失的图像或查看日志!(?)
更新:在这方面,Windows 和 Linux 的行为可能有所不同。Windows 在文件系统方面有额外的限制,但这不一定会对 Linux 系统产生同样的影响。(在生产环境中,Apache 在 Windows 上运行的情况并不常见。)
而不是使用 Apache<If>
表达式(它是合并如果较晚处理,我倾向于使用 mod_rewrite(处理得早)。直接在容器中<VirtualHost>
(而不是在<Directory>
部分中)尝试以下操作:
RewriteEngine On
# Serve a "410 Gone" for any URL that starts with "spaces"
RewriteRule ^/\s - [G]
或者,将此类请求通过 301 重定向到“正确”的 URL:
# Redirect to remove the "spaces"
RewriteRule ^/\s+(/.*) $1 [R=301,L]
mod_rewrite 指令服务器(或者虚拟主机)上下文被处理前该请求被映射到文件系统。