工大后院

 找回密码
 加入后院

扫一扫,访问微社区

QQ登录

只需一步,快速开始

搜索
查看: 2993|回复: 11

简单防盗链程序(JSP)

[复制链接]
发表于 2007-5-26 00:23 | 显示全部楼层 |阅读模式
防盗链,现在似乎挺流行的。特别是图片,防盗链后害得我们不能链接来用。是利是弊,暂不表。

下面是一个简单的过滤器,实现简单的图片防盗链功能。

提示:商业应用中的防盗链要复杂得多,而且价格不菲。下面程序只作学习和玩耍而已。


  1. package myfilter;
  2. import java.io.IOException;
  3. import javax.servlet.Filter;
  4. import javax.servlet.FilterChain;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.ServletOutputStream;
  8. import javax.servlet.ServletRequest;
  9. import javax.servlet.ServletResponse;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. public class PictureFilter implements Filter {
  13. private static String weburl;
  14. public void doFilter(ServletRequest request, ServletResponse response,
  15.    FilterChain chain) throws IOException, ServletException {
  16.   if (weburl != null) {
  17.    HttpServletRequest req = (HttpServletRequest) request;
  18.    HttpServletResponse resp = (HttpServletResponse) response;
  19.    String url = req.getHeader("Referer");
  20.    if (req.getSession(false) == null) {
  21.     if (url == null || url.indexOf(weburl) < 0) {
  22.      ServletOutputStream out = resp.getOutputStream();
  23.      out.println("dao lian is bu dui de");
  24.      return;
  25.     }
  26.    }
  27.   }
  28.   chain.doFilter(request, response);
  29. }
  30. public void destroy() {
  31.   weburl = null;
  32. }
  33. public void init(FilterConfig config) throws ServletException {
  34.   weburl = config.getInitParameter("weburl");
  35. }
  36. }
复制代码


在web.xml文件中如此配置


  1. <filter>
  2.   <filter-name>PictureFilter</filter-name>
  3.   <filter-class>myfilter.PictureFilter</filter-class>
  4.   <init-param>
  5.    <param-name>weburl</param-name>
  6.    <param-value>http://127.0.0.1:8080/myweb</param-value>
  7.   </init-param>
  8. </filter>
  9. <filter-mapping>
  10.   <filter-name>PictureFilter</filter-name>
  11.   <url-pattern>*.jpg</url-pattern>
  12. </filter-mapping>
  13.   <filter-mapping>
  14.   <filter-name>PictureFilter</filter-name>
  15.   <url-pattern>*.gif</url-pattern>
  16. </filter-mapping>
  17.   <filter-mapping>
  18.   <filter-name>PictureFilter</filter-name>
  19.   <url-pattern>*.jpeg</url-pattern>
  20. </filter-mapping>
复制代码


就这么简单。


下面略加说明。

HTTP Referer二三事

授权方式:署名,非商业用途,保持一致,转载时请务必以超链接(http://www.fwolf.com/blog/post/320)的形式标明文章原始出处和作者信息及本声明。
什么是HTTP Referer简言之,HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。
Referer其实应该是英文单词Referrer,不过拼错的人太多了,所以编写标准的人也就将错就错了。
我的问题我刚刚把feed阅读器改变为Gregarius,但他不像我以前用的liferea,访问新浪博客的时候,无法显示其中的图片,提示“此图片仅限于新浪博客用户交流与沟通”,我知道,这就是HTTP Referer导致的。
由于我上网客户端配置的特殊性,首先怀疑是squid的问题,但通过实验排除了,不过同时发现了一个Squid和Tor、Privoxy协同使用的隐私泄露问题,留待以后研究。
Gregarius能处理这个问题么?答案是否定的,因为Gregarius只是负责输出html代码,而对图像的访问是有客户端浏览器向服务器请求的。
不过,安装个firefox扩展也许能解决问题,文中推荐的”Send Referrer”我没有找到,但发现另外一个可用的:”RefControl“,可以根据访问网站的不同,控制使用不同的Referer。
但是我不喜欢用Firefox扩展来解决问题,因为我觉得他效率太低,所以我用更好的方式——Privoxy。
Privoxy真棒在Privoxy的default.action中添加两行:
{+hide-referer{forge}}album.sina.com.cn这样Gregarius中新浪博客的图片就出来了吧?+hide-referer是Privoxy的一个过滤器,设置访问时对HTTP Referer的处理方式,后面的forge代表用访问地址当作Refere的,还可以换成block,代表取消Referer,或者直接把需要用的Referer网址写在这里。
用Privoxy比用Firefox简单的多,赶紧吧。
From https to http我还发现,从一个https页面上的链接访问到一个非加密的http页面的时候,在http页面上是检查不到HTTP Referer的,比如当我点击自己的https页面下面的w3c xhtml验证图标(网址为http://validator.w3.org/check?uri=referer),从来都无法完成校验,提示:
No Referer header found!原来,在http协议的rfc文档中有定义:
15.1.3 Encoding Sensitive Information in URI's...   Clients SHOULD NOT include a Referer header field in a (non-secure)   HTTP request if the referring page was transferred with a secure   protocol.这样是出于安全的考虑,访问非加密页时,如果来源是加密页,客户端不发送Referer,IE一直都是这样实现的Firefox浏览器也不例外。但这并不影响从加密页到加密页的访问。
Firefox中关于Referer的设置都在里,有两个键值:
  • network.http.sendRefererHeader (default=2)
    设置Referer的发送方式,0为完全不发送,1为只在点击链接时发送,在访问页面中的图像什么的时候不发送,2为始终发送。参见Privacy Tip #3: Block Referer Headers in Firefox
  • network.http.sendSecureXSiteReferrer (default=true)
    设置从一个加密页访问到另外一个加密页的时候是否发送Referer,true为发送,false为不发送。
利用Referer防止图片盗链虽然Referer并不可靠,但用来防止图片盗链还是足够的,毕竟不是每个人都会修改客户端的配置。实现一般都是通过apache的配置文件,首先设置允许访问的地址,标记下来:
# 只允许来自domain.com的访问,图片可能就放置在domain.com网站的页面上SetEnvIfNoCase Referer "^http://www.domain.com/" local_ref# 直接通过地址访问SetEnvIf Referer "^$" local_ref然后再规定被标记了的访问才被允许:
<FilesMatch ".(gif|jpg)">Order Allow,DenyAllow from env=local_ref</FilesMatch>或者
<Directory /web/images>   Order Deny,Allow   Deny from all   Allow from env=local_ref</Directory>这方面的文章网上很多,参考:
不要使用Rerferer的地方不要把Rerferer用在身份验证或者其他非常重要的检查上,因为Rerferer非常容易在客户端被改变,不管是通过上面介绍的Firefox扩展,或者是Privoxy,甚至是libcurl的调用,所以Rerferer数据非常之不可信。
如果你想限制用户必须从某个入口页面访问的话,与其使用Referer,不如使用session,在入口页面写入session,然后在其他页面检查,如果用户没有访问过入口页面,那么对应的session就不存在,参见这里的讨论。不过和上面说的一样,也不要过于相信这种方式的“验证”结果。
个人感觉现在Rerferer除了用在防盗链,其他用途最多的就是访问统计,比如统计用户都是从哪里的链接访问过来的等等。
This entry was posted on Saturday, May 5th, 2007 at 16:35:48 and is filed under Internet, Apache, Tools. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

评分

1

查看全部评分

发表于 2007-6-1 18:53 | 显示全部楼层
觉得String url = req.getHeader("Referer");有问题。。
第一次直接打开你网站的图片也会显示盗链吗?
回复

使用道具 举报

 楼主| 发表于 2007-6-1 19:03 | 显示全部楼层
确实如楼上所言
回复

使用道具 举报

发表于 2007-6-1 19:44 | 显示全部楼层
应该是
url != null || url.indexOf(weburl) < 0
回复

使用道具 举报

发表于 2007-6-1 19:50 | 显示全部楼层
下面是我根据LZ的文章写的。。


PicFilter.java

package cn.burt;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class PicFilter implements Filter {         
          private String host=null;
          public void destroy() {
                    host=null;
          }         
          public void doFilter(ServletRequest req, ServletResponse res,
                              FilterChain chain) throws IOException, ServletException {
                    HttpServletRequest request=(HttpServletRequest)req;                    
                    String from=request.getHeader("referer");
                    if(from!=null&&!from.startsWith(host)){                              
                              HttpServletResponse response=(HttpServletResponse)res;                                                  
                              response.setContentType("image/jpeg");         
                              OutputStream os=response.getOutputStream();
                              FileInputStream fis=new FileInputStream(request.getRealPath("stealinglink.jpg"));
                              byte[] content=new byte[fis.available()];
                              fis.read(content);
                              os.write(content);
                              fis.close();
                              os.close();                                                            
                    }else{
                              chain.doFilter(req,res);
                    }
          }
          public void init(FilterConfig config) throws ServletException {
                    host=config.getInitParameter("host");
          }
}

web.xml

          <filter>
                    <filter-name>PicFilter</filter-name>
                    <filter-class>cn.burt.PicFilter</filter-class>
                    <init-param>
                              <param-name>host</param-name>
                              <param-value>http://my.burt.cn:8080</param-value>
                    </init-param>
          </filter>
          <filter-mapping>
                    <filter-name>PicFilter</filter-name>
                    <url-pattern>*.jpg</url-pattern>
          </filter-mapping>

stealinglink.jpg是存放在WebRoot目录下的图片
stealinglink.JPG
回复

使用道具 举报

 楼主| 发表于 2007-6-1 20:07 | 显示全部楼层
我还是比较喜欢让它输出“"dao lian is bu dui de”这行字!
回复

使用道具 举报

发表于 2007-6-1 20:27 | 显示全部楼层
其实输出随机图片不是更好……
回复

使用道具 举报

发表于 2007-6-2 00:54 | 显示全部楼层
原帖由 try 于 2007-6-1 20:07 发表
我还是比较喜欢让它输出“"dao lian is bu dui de”这行字!



别人看得到吗。。。

盗链的人就是用<img src="">来引用你图片啊。。
回复

使用道具 举报

发表于 2007-6-2 00:56 | 显示全部楼层
原帖由 iptton 于 2007-6-1 20:27 发表
其实输出随机图片不是更好……



没有威慑警告的作用。。
回复

使用道具 举报

发表于 2007-6-2 00:59 | 显示全部楼层
用来输出我的头像也不错  
回复

使用道具 举报

发表于 2007-6-2 10:13 | 显示全部楼层
ma jia of powerwind。。。
回复

使用道具 举报

发表于 2007-6-15 19:39 | 显示全部楼层
破解的方法太简单了。
写一个读取页面的,自己定义Referer就行了
召唤高手写一个,然后楼主再写一个让破解失效的,
然后高手再想个方法破解,然后楼主再反破解。。。。
最后,一个最完美的防盗链产生了。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入后院

本版积分规则

QQ|Archiver|手机版|小黑屋|广告业务Q|工大后院 ( 粤ICP备10013660号 )

GMT+8, 2025-8-30 21:16

Powered by Discuz! X3.5

Copyright © 2001-2024 Tencent Cloud.

快速回复 返回顶部 返回列表