2010-10-29 3 views
1

Как вы предотвращаете хотлинкинг на автономном сервере Java Webapp, таком как Tomcat?Как предотвратить hotlinking на автономном сервере Java Webapp?

+0

Вот пример того, почему и как, на Apache, вы можете предотвратить хотлинкинга: http://www.dagondesign.com/articles/hotlink-protection-with-htaccess/ Мой случай Я использую Tomcat в автономном режиме. – SyntaxT3rr0r

+0

с таким хорошим и полезным ответом. Я не знаю, какой из них принять. Я дал всем +1, но я не знаю, какой из них выбрать как * правильный. Это немного странно на SO methinks: я имею в виду, что вы должны принять один ... – SyntaxT3rr0r

ответ

2

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

EDIT: Что the article you've linked to описывает это правило, на основе заголовка 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] 

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

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

+0

Я действительно не понимаю этого, не могли бы вы рассказать мне больше? :) Вы имеете в виду, что все запросы, сделанные, скажем, изображениями, со страницы, на которой я служил, уже включают «Referer», на который я мог проверить? Или мне нужно, в дополнение к фильтру, также добавить конкретный «Referer»? – SyntaxT3rr0r

+0

HTTP указывает заголовок «Referrer», который содержит местоположение, из которого клиент получил адрес, который он запрашивает в настоящее время. Для встроенных изображений это URL-адрес страницы, которую браузер загружает. –

+0

@ Tassos Bassoukos действительно, но спецификация HTTP говорит о том, что «Referer» (одиночный «r»), к сожалению. – Bruno

2

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

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

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

+0

На самом деле, фильтр urlrewrite, о котором я упоминал, является эквивалентом Java для mod_rewrite от Apache, который используется в статье, на которую вы ссылались, поэтому вам будет очень легко имитировать поведение, описанное в этой статье. – jjmontes

2

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

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:

URLRewriteFilter
<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> 
+0

Вы уверены, что это 'hsr.getHeader (« HTTP_REFERER »)', а не 'hsr.getHeader (« Referer »)'? Я думаю, что это должно быть имя заголовка, а не какое-то ключевое слово конфигурации. – Bruno

+0

Мой плохой. Это «Referer». Благодарю. –

3

Используйте Таки (как уже отмечалось другими, уже косвенно). Из 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>