【问题标题】:How to prevent hotlinking on standalone Java webapp server?如何防止独立 Java webapp 服务器上的盗链?
【发布时间】:2011-05-02 08:40:40
【问题描述】:

如何防止像 Tomcat 这样的独立 Java webapp 服务器上的热链接?

【问题讨论】:

  • 这是一个示例,说明为什么以及如何在 Apache 上防止盗链:dagondesign.com/articles/hotlink-protection-with-htaccess 我的情况不同,我在独立模式下使用 Tomcat。
  • 有这么多好的和有用的答案,我不知道该接受哪一个。我给了每个人+1,但我不知道选择哪一个作为正确的。这在我看来有点奇怪:我的意思是,你必须接受一个事实......

标签: java tomcat hotlinking


【解决方案1】:

我不确定它是否已经存在,但您可以轻松编写 Filter 来检查是否存在与适当模式匹配的 Referer 标头(如您发布的链接中所述)。

编辑: the article you've linked to 描述的是基于Referer HTTP 标头的规则(由浏览器发送以指示从哪个页面获取链接)。 Apache Httpd 上的.htaccess 中的以下规则与mod_rewrite 或多或少意味着,如果Referer 标头与http://(www\\.)?yoursite\\.com 模式不匹配,则重定向到/images/hotlink.jpeg

RewriteEngine on 
RewriteCond %{HTTP_REFERER} . 
RewriteCond %{HTTP_REFERER} !^http://(www\\.)?yoursite\\.com [NC] 
RewriteRule \\.(gif|jpe?g)$ /images/hotlink.$1 [L]

过滤器是 webapps 中的一种标准机制,用于在请求发送到 servlet 进行处理之前拦截请求(如果需要,它们可以选择不重定向到 servlet)。

您将覆盖过滤器中的doFilter(ServletRequest request, ServletResponse response, FilterChain chain),测试request.getHeader("Referer") 是否匹配正确的模式,如果是,则调用chain.doFilter(request, response),否则将重定向响应发送到其他图像(即“热链接”或其他),可能带有 403 状态码。

【讨论】:

  • 我不太明白,你能告诉我更多吗? :) 你的意思是,从我自己服务的页面上对图片提出的所有请求都已经包含一个我可以检查的“推荐人”?还是除了过滤器之外,我还需要添加特定的“推荐人”吗?
  • HTTP 指定一个“Referrer”标头,其中包含客户端获取当前请求地址的位置。对于嵌入式图像,它是浏览器当前正在加载的页面的 URL。
  • @Tassos Bassoukos 确实如此,但不幸的是,HTTP 规范拼写为Referer(单个“r”)。
【解决方案2】:

您可以像布鲁诺所说的那样检查合适的推荐人。

每个 HTTP 请求都包含一个引用标头,其中包含链接到当前请求的 URL(或者,对于图像,是引用该图像的页面)的 URL。在您的情况下,它应该包含一个适当的引用 URL,它应该属于您自己的网站。

为了检测不允许的引用,我认为您可以使用像 http://www.tuckey.org/urlrewrite/ 这样的过滤器。您可以配置一个简单的规则来匹配不是来自您自己站点的每个图像请求,并禁止访问或将该 URL 重写为自定义的“Hotlinking not allowed”图像。

【讨论】:

  • 事实上,我提到的 urlrewrite 过滤器是 Apache 的 mod_rewrite 的 Java 等价物,它在您引用的文章中使用,因此您应该很容易模仿该文章中描述的行为。
【解决方案3】:

这是一个示例过滤器实现:

public class HotLinkFilter implements Filter{

    private final Map<Pattern, Pattern> PATTERNS =
        new ConcurrentHashMap<Pattern, Pattern>();

    private void addPatterns(final String targetPattern,
        final String referrerPattern){
        PATTERNS.put(Pattern.compile(targetPattern),
            Pattern.compile(referrerPattern));
    }

    @Override
    public void init(final FilterConfig config) throws ServletException{
        @SuppressWarnings("unchecked")
        final Enumeration<String> parameterNames =
            config.getInitParameterNames();
        while(parameterNames.hasMoreElements()){
            final String nextParam = parameterNames.nextElement();
            if(nextParam.startsWith("pattern")){
                final String[] patterns =
                    config.getInitParameter(nextParam).split("\\s+");
                if(patterns.length == 2){
                    addPatterns(patterns[0], patterns[1]);
                }
            }
        }
    }

    @Override
    public void doFilter(final ServletRequest request,
        final ServletResponse response,
        final FilterChain chain) throws IOException, ServletException{

        if(request instanceof HttpServletRequest){
            final HttpServletRequest hsr = (HttpServletRequest) request;
            final String referrer = hsr.getHeader("Referer");
            boolean valid = true;
            if(referrer != null){
                final String requestUrl = hsr.getRequestURL().toString();
                for(final Entry<Pattern, Pattern> entry : PATTERNS.entrySet()){
                    if(entry.getKey().matcher(requestUrl).matches()
                        && !entry.getValue().matcher(referrer).matches()){
                        valid = false;
                        break;
                    }
                }
            }
            if(valid){
                chain.doFilter(request, response);
            } else{
                // this is probably not the correct thing to do
                throw new ServletException("Hotlinking not allowed");
            }

        }

    }

    @Override
    public void destroy(){
    }

}

它使用正则表达式模式图。如果请求匹配左侧的模式并且存在引用者,那么我们检查引用者是否匹配右侧的模式。您可以在 web.xml 中进行配置:

<filter>
    <filter-name>Hotlink-Filter</filter-name>
    <filter-class>com.yourcompany.HotLinkFilter</filter-class>
    <init-param>
        <param-name>pattern1</param-name>
        <param-value>http://.*\.mysite.com/.*\.(jpe?g|gif|png) 
        http://.*\.mysite.com/.*</param-value>
    </init-param>
</filter>

【讨论】:

  • 您确定是hsr.getHeader("HTTP_REFERER") 而不是hsr.getHeader("Referer")?我认为它应该是实际的标题名称,而不是一些配置关键字。
  • 我的错。是“推荐人”。谢谢。
【解决方案4】:

使用 Tuckey 的 URLRewriteFilter(正如其他人已经间接提到的那样)。来自documentation

<rule>
    <name>Blocked Inline-Images</name>
    <note>
        Assume we have under http://www.quux-corp.de/~quux/ some pages with inlined GIF graphics. These graphics are
        nice, so others directly incorporate them via hyperlinks to their pages. We don't like this practice because
        it adds useless traffic to our server.

        While we cannot 100% protect the images from inclusion, we can at least restrict the cases where the browser
        sends a HTTP Referer header.

        RewriteCond %{HTTP_REFERER} !^$
        RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
        RewriteRule .*\.gif$ - [F]
    </note>
    <condition name="referer" operator="notequal">^$</condition>
    <condition name="referer" operator="notequal">^http://www.quux-corp.de/~quux/.*$</condition>
    <from>.*\.gif$</from>
    <set type="status">403</set>
    <to>null</to>
</rule>

<rule>
    <name>Blocked Inline-Images example 2</name>
    <note>
        RewriteCond %{HTTP_REFERER} !^$
        RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$
        RewriteRule ^inlined-in-foo\.gif$ - [F]
    </note>
    <condition name="referer" operator="notequal">^$</condition>
    <condition name="referer" operator="notequal">.*/foo-with-gif\.html$</condition>
    <from>^inlined-in-foo\.gif$</from>
    <set type="status">403</set>
    <to>null</to>
</rule>

【讨论】:

    猜你喜欢
    • 2016-03-08
    • 2011-08-04
    • 1970-01-01
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    相关资源
    最近更新 更多