1.我想让我的网站上从一对夫妇不同的爬虫程序和排除所有其他图像爬行。
1.我希望允许至少一个文件夹中的图像不被任何请求阻止。
1.我不想阻止来自我自己网站上的访问者的图片请求。
1.我不想把我的域名包含在.htaccess文件中以便于移植。
我之所以在这里问这个问题,而不是简单地自己测试下面的代码,是因为我自己工作,没有大学可以问,也没有外部资源可以测试。我认为我得到的是正确的,但我发现.htaccess规则非常混乱,我不知道我甚至不知道在这一点上。
RewriteCond %{HTTP_REFERER} !^$ [OR]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?bing\..+$ [NC,OR]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?facebook\..+$ [NC,OR]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?google\..+$ [NC,OR]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?instagram\..+$ [NC,OR]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?linkedin\..+$ [NC,OR]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?reddit\..+$ [NC,OR]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?twitter\..+$ [NC,OR]
RewriteCond %{REQUEST_URI} !^/cross-origin-resources/ [NC,OR]
RewriteCond %{HTTP_HOST}@@%{HTTP_REFERER} !^([^@]*)@@https?://\1/.* [NC]
RewriteRule \.(bmp|gif|jpe?g|png|webp)$ - [F,L,NC]
我已经在htaccess测试器上测试过了,看起来不错,但在使用以下URL测试时,确实抱怨倒数第二行:http://www.example.co.uk/poignant/foo.webp
1条答案
按热度按时间zaq34kh61#
RewriteCond
指令)将始终成功,请求将 * 始终 * 被阻止。您有一系列的"求反"条件,这些条件是"或"的。只有当所有条件都匹配时,这些条件才会"失败"(即"不"阻塞请求),而这是不可能的。(例如,
Referer
头不能是bing
* 和 *facebook
。)您需要删除所有
RewriteCond
指令上的OR
标志,以便它们是隐式 * AND'd * 的。顺便说一句,@StephenOstermiller在评论中建议将
HTTP_REFERER
检查合并为一个检查(这是一个很好的建议),这相当于拥有单独的条件 * AND'd *,而不是OR
'd(正如您最初发布的那样)。1.我想让我的网站上从一对夫妇不同的爬虫程序和排除所有其他图像爬行。
一旦你更正了上面提到的
OR
/AND,这个规则将可能允许所有机器人抓取你的网站图片,因为机器人通常不发送Referer
标题。这些指令实际上并不是关于"抓取",它们允许某些网站在他们的域名上显示你的图片(即热链接)。这可能是意图,然而,这不是你在第一点中所说的。(To阻止爬虫程序 * 抓取 * 您的站点,您需要检查
User-Agent
请求头,即HTTP_USER_AGENT
-这可能在单独的规则中完成更好。这是一个小问题,但是正则表达式末尾的
+$
是多余的。当你只对 * hostname * 感兴趣时,没有必要匹配整个Referer
。尽管这些网站可能设置了Referrer-Policy,以防止URL路径在Referer
头中被(浏览器)发送,但它仍然是不必要的。在评论中,你问这一行是做什么的。这满足了你列表中的第3点和第4点,所以它是肯定需要的。它确保了请求的
Host
头(HTTP_HOST
)匹配Referer
中的 * hostname *。所以请求来自同一个站点。另一种方法是将域硬编码为 * condition *,这是您试图避免的。
(同样,正则表达式的尾部
.*
是不必要的,应该删除。)这是通过在正则表达式中对与 * TestString *(第一个参数)中的
HTTP_HOST
匹配的HTTP_REFERER
使用内部反向引用\1
来实现的。@@
字符串只是一个不出现在HTTP_HOST
或HTTP_REFERER
服务器变量中的任意字符串。如果您展开 * TestString * 来查看匹配的内容,这一点会更清楚。例如,如果您从主页(即
https://example.com/
)向https://example.com/myimage.jpg
发出内部请求,则RewriteCond
指令中的 * TestString * 为:然后将其与正则表达式
^([^@]*)@@https?://\1/
进行匹配(* CondPattern * 上的!
前缀是一个 * 运算符 *,是参数的一部分,而不是正则表达式的一部分)。([^@]*)
-第一个捕获组捕获example.com
(HTTP_HOST
的值)。@@https?://
-仅匹配 * 测试字符串 * 中的@@https://
(HTTP_REFERER
的一部分)。\1
-这是一个内部反向引用。因此,它必须与从第一个捕获组(上面的#1)捕获的值匹配。在本示例中,它必须与example.com
匹配。它确实匹配,因此匹配成功。1.* CondPattern * 上的
!
前缀(严格来说不是正则表达式的一部分)对整个表达式求反,因此当正则表达式 * 不 * 匹配时,条件成功。因此,在上面的示例中,正则表达式匹配,因此条件失败(因为它被取反),因此规则不会被触发,请求也不会被阻止。
但是,如果从外部站点(例如
https://external-site.example/
)向https://example.com/myimage.jpg
发出请求,则RewriteCond
指令中的 * TestString * 为:按照上述步骤,正则表达式匹配失败(因为
external-site.example
与example.com
不匹配)。因此,* negated * 条件成功,规则被触发,请求被阻止。(除非其他条件之一 * failed *。)请注意,在所写的条件下,
www.example.com
与example.com
不同。例如,如果您在example.com
上,并且使用www.example.com
来使用图像的绝对URL,则正则表达式将无法匹配,请求将被阻止。这可能会合并到正则表达式中。但这在很大程度上是一种边缘情况,可以通过配置中较早的规范301重定向来避免。这允许
Referer
标头为空(或不存在)。你"可能"需要这样做。它允许机器人抓取你的图片。它允许直接请求图片。它还允许用户选择禁止Referer
标头,以便能够在 * 你的 * 站点上查看你的图片。然而,现在也有可能一个网站设置一个 * Referrer-Policy *,完全抑制(浏览器)发送的
Referer
报头,从而绕过你的热链接保护。次要问题,但使用
F
标志时不需要L
标志(这是隐含的)。你真的在提供
.bmp
图像吗?!* 题外话:* 网站不一定"热链接"
一些外部网站(bing、Facebook、Google、Instagram、LinkedIn、Reddit、twitter等)并不一定会"热链接"图片,而是自己制作(调整大小/压缩)图片的"副本"(bot发出检索图片的初始请求--没有
Referer
--所以请求不会被阻止)。因此,无论如何,在"hotlink-protection"脚本中明确允许其中一些站点可能是不必要的。
总结
考虑到以上几点,指令应该看起来更像这样: