Как предотвратить хотлинкинг на автономном сервере веб-приложений Java? - PullRequest
1 голос
/ 29 октября 2010

Как предотвратить хотлинкинг на автономном сервере веб-приложений Java, таком как Tomcat?

Ответы [ 4 ]

3 голосов
/ 29 октября 2010

Используйте Tuckey's URLRewriteFilter (как уже упоминалось другими косвенно). Из документации :

<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>
2 голосов
/ 29 октября 2010

Вы можете проверить подходящего реферера, как сказал Бруно.

Каждый HTTP-запрос содержит заголовок реферера, который содержит URL-адрес, связанный с текущим запрашиваемым URL-адресом (или, для изображений, страницу, ссылающуюся на изображение). В вашем случае он должен содержать соответствующий URL-адрес реферера, который должен принадлежать вашему сайту.

Чтобы обнаружить недопустимых рефереров, я думаю, вы могли бы использовать фильтр типа http://www.tuckey.org/urlrewrite/. Вы можете настроить простое правило, которое соответствует каждому запросу на изображение, не исходящему от вашего собственного сайта, и запретить доступ или переписать этот URL к пользовательскому изображению «Горячая ссылка не разрешена».

2 голосов
/ 29 октября 2010

Вот пример реализации фильтра:

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(){
    }

}

Используется карта шаблонов Regex.Если запрос соответствует шаблону с левой стороны и присутствует реферер, мы проверяем, соответствует ли реферер шаблону с правой стороны.Вы можете настроить это в файле 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>
2 голосов
/ 29 октября 2010

Я не уверен, существует ли он уже, но вы могли бы легко написать Filter , который проверяет, есть ли заголовок Referer, который соответствует соответствующему шаблону (как описано в ссылке, которую вы опубликовали) ).

EDIT: статья, на которую вы ссылаетесь , описывает правило, основанное на HTTP-заголовке Referer (который отправляется браузерами, чтобы указать, с какой страницы была получена ссылка). Следующие правила в .htaccess для Apache Httpd с 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]

Фильтры - это стандартный механизм в веб-приложениях для перехвата запросов, прежде чем они отправляются сервлету для обработки (и они могут не перенаправлять их на сервлет, если это необходимо).

Вы бы переопределили doFilter(ServletRequest request, ServletResponse response, FilterChain chain) в своем фильтре, проверили, соответствует ли request.getHeader("Referer") правильному шаблону, если это так, вызовите chain.doFilter(request, response), в противном случае отправьте ответ о перенаправлении на какое-то другое изображение (которое скажет «горячая ссылка» или что-то еще ), возможно, с кодом состояния 403.

...