问题
How do you prevent hotlinking on a standalone Java webapp server like Tomcat?
回答1:
Use Tuckey's URLRewriteFilter (as mentioned by others already indirectly). From the 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>
回答2:
You can check for an appropriate referer as Bruno said.
Every HTTP request contains a referer header that contains the URL that linked to the current URL being requested (or, for images, the page that referenced the image). In your case, it should contain an appropriate referer URL, which should belong to your own site.
In order to detect disallowed referers, I think you could use a filter like http://www.tuckey.org/urlrewrite/ . You can configure a simple rule that matches every image request not coming from your own site, and forbid the access or rewrite that URL to a custom 'Hotlinking not allowed' image.
回答3:
I'm not sure whether it already exists, but you could easily write a Filter that checks whether there's a Referer
header that matches the appropriate pattern (as described in the link you've posted).
EDIT:
What the article you've linked to describes is a rule based on the Referer
HTTP header (which is sent by browsers to indicate from which page the link was obtained).
The following rules in .htaccess
on Apache Httpd with mod_rewrite
more or less mean, if the Referer
header doesn't match the http://(www\\.)?yoursite\\.com
pattern, then redirect to /images/hotlink.jpeg
.
RewriteEngine on
RewriteCond %{HTTP_REFERER} .
RewriteCond %{HTTP_REFERER} !^http://(www\\.)?yoursite\\.com [NC]
RewriteRule \\.(gif|jpe?g)$ /images/hotlink.$1 [L]
Filters are a standard mechanism in webapps for intercepting requests before they're sent to the servlet for processing (and they can chose not to redirect to the servlet if needed).
You would override the doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
in your Filter, test whether request.getHeader("Referer")
matches the right pattern, if so, call chain.doFilter(request, response)
, otherwise send a redirection response to some other image (that would say "hotlink" or whatever), possibly with a 403 status code.
回答4:
Here's an example filter implementation:
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(){
}
}
It uses a map of Regex patterns. If a request matches the pattern on the left side and a referrer is present, then we check if the referrer matches the pattern on the right side. You can configure this in the 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>
来源:https://stackoverflow.com/questions/4051222/how-to-prevent-hotlinking-on-standalone-java-webapp-server