使用白名单 htaccess 停止图片盗链

Stop image hotlinking with whitelist htaccess

一个大图片画廊需要一个带有 google、bing、yahoo 等白名单的热链接脚本。 在网上我找到了很多例子,但它们都有不同的语法。

示例 1:

RewriteCond %{HTTP_REFERER} !^http://(.+\.)?google/.*$ [NC]

示例 2:

RewriteCond %{HTTP_REFERER} !google\. [NC]

示例 3:

RewriteCond %{HTTP_REFERER} !google. [NC] 

示例 4:

SetEnvIfNoCase Referer "^(http|https)://.*google.*" whitelist

示例 5:

RewriteCond %{HTTP_REFERER} !^http://(.+\.)?google/.*$ [NC]

问题 1:使用域通配符哪个最快最正确?
问题 2:为什么在示例 5 中不需要 http:// infront?

我做了什么:

RewriteCond %{HTTP_REFERER}  !my-domain\.                   [NC]
RewriteCond %{HTTP_REFERER}  !search\?q=cache               [NC]
RewriteCond %{HTTP_REFERER}  !google\.                      [NC]
RewriteCond %{HTTP_REFERER}  !twitter\.                     [NC]
RewriteCond %{HTTP_REFERER}  !facebook\.                    [NC]
RewriteCond %{HTTP_REFERER}  !googleusercontent\.           [NC]
RewriteCond %{HTTP_REFERER}  !bing\.                        [NC]
RewriteCond %{HTTP_REFERER}  !pinterest\.                   [NC]
RewriteCond %{HTTP_REFERER}  !yahoo\.                       [NC]
RewriteCond %{REQUEST_URI}   !^/hotlink\.jpg$               [NC]

RewriteRule \.(gif|jpg|png)$ http://domain.tld/hotlink.jpg  [R,NC,L]

问题三:只有1行是不是更快?怎么写成这样:

google|facebook|bing|etc

我做了什么:

RewriteCond %{HTTP_REFERER}  !my-domain\. [NC]
RewriteCond %{HTTP_REFERER} !(google|googleusercontent|yahoo|bing|facebook|pinterest|etc.) [NC]
RewriteCond %{REQUEST_URI}   !^/hotlink\.jpg$               [NC]
RewriteRule \.(gif|jpg|png)$ http://my-domain.tld/hotlink.jpg  [R,NC,L]

这不是很科学,但我猜 ored 选项会最长。

我在 http://www.regex101.com 上尝试使用此正则表达式:(google|googleusercontent|yahoo|bing|facebook|pinterest) 以匹配 http://www.yahoo.com

它用了 87 个步骤(你可以在网站上的正则表达式调试器中看到它)而只用了 7 个步骤来匹配正则表达式 yahoo

所以大约 7 x 9(RewriteCond 的数量)给出了 63 个步骤,其中 ored 正则表达式采取了 87 个步骤,所以我认为在任何情况下使用简单的正则表达式和多个 RewriteCond 直到步骤交叉(正则表达式将采取了可预测的步数,尝试使用完整的 ored 和最后的匹配来了解最大步数)。

再一次:那里没有科学依据,myabe 调用 9 测试比调用复杂测试要花更多的时间,也许处于调试模式的 apache 可以告诉我所用的时间,但我不确定。

偏爱其中一个仍然是一个选择问题,因为我很确定在服务器因请求数量而停滞之前它不会产生明显的差异。


对于匹配,domain\. 就足够了,在我看来不需要使用更复杂的东西,也许你可能会遇到一些边缘情况,其中 referer 的其他地方有 domain....

点之前的 \ 对于匹配一个乱码点很重要,而不是匹配正则表达式中 domain 之后的任何字符。