HttpClient使用过程中的安全隐患
创始人
2024-07-25 20:20:17
0

HttpClient使用过程中的安全隐患,这个有些标题党。因为这本身不是HttpClient的问题,而是使用者的问题。

安全隐患场景说明:

一旦请求大数据资源,则HttpClient线程会被长时间占有。即便调用了org.apache.commons.httpclient.HttpMethod#releaseConnection()方法,也无济于事。

如果请求的资源是应用可控的,那么不存在任何问题。可是恰恰我们应用的使用场景是,请求资源由用户自行输入,于是乎,我们不得不重视这个问题。

我们跟踪releaseConnection代码发现:

org.apache.commons.httpclient.HttpMethodBase#releaseConnection()

 

  1. public   void  releaseConnection() {  
  2.       try  {  
  3.           if  ( this .responseStream  !=   null ) {  
  4.               try  {  
  5.                    //  FYI - this may indirectly invoke responseBodyConsumed.   
  6.                   this .responseStream.close();  
  7.              }  catch  (IOException ignore) {  
  8.              }  
  9.          }  
  10.      }  finally  {  
  11.           ensureConnectionRelease();  
  12.      }  
  13.  }  

 

org.apache.commons.httpclient.ChunkedInputStream#close()

 

  1. public   void  close()  throws  IOException {  
  2.        if  ( ! closed) {  
  3.            try  {  
  4.                if  ( ! eof) {  
  5.                  exhaustInputStream( this );  
  6.               }  
  7.          }  finally  {  
  8.               eof  =   true ;  
  9.               closed  =   true ;  
  10.           }  
  11.       }  
  12.   }  

 

org.apache.commons.httpclient.ChunkedInputStream#exhaustInputStream(InputStream inStream)

 

  1. static   void  exhaustInputStream(InputStream inStream)  throws  IOException {  
  2.       //  read and discard the remainder of the message   
  3.       byte  buffer[]  =   new   byte [ 1024 ];  
  4.       while  (inStream.read(buffer)  >=   0 ) {  
  5.          ;  
  6.       }  
  7.  }  

 

看到了吧,所谓的丢弃response,其实是读完了一次请求的response,只是不做任何处理罢了。

想想也是,HttpClient的设计理念是重复使用HttpConnection,岂能轻易被强制close呢。

怎么办?有朋友说,不是有time out设置嘛,设置下就可以下。

我先来解释下Httpclient中两个time out的概念:

1.public static final String CONNECTION_TIMEOUT = "http.connection.timeout";

即创建socket连接的超时时间:java.net.Socket#connect(SocketAddress endpoint, int timeout)中的timeout

2.public static final String SO_TIMEOUT = "http.socket.timeout";

即read data过程中,等待数据的timeout:java.net.Socket#setSoTimeout(int timeout)中的timeout

而在我上面场景中,这两个timeout都不满足,确实是由于资源过大,而占用了大量的请求时间。

问题总是要解决的,解决思路如下:

1.利用DelayQueue,管理所有请求

2.利用一个异步线程监控,关闭超长时间的请求

演示代码如下:

 

  1. public   class  Misc2 {  
  2.       
  3.          private   static   final  DelayQueue < Timeout >  TIMEOUT_QUEUE  =   new  DelayQueue < Timeout > ();  
  4.       
  5.          public   static   void  main(String[] args)  throws  Exception {  
  6.              new  Monitor().start();  //  超时监控线程   
  7.       
  8.              new  Request( 4 ).start(); //  模拟***个下载   
  9.              new  Request( 3 ).start(); //  模拟第二个下载   
  10.             new  Request( 2 ).start(); //  模拟第三个下载   
  11.        }  
  12.      
  13.         /**   
  14.         * 模拟一次HttpClient请求  
  15.         *   
  16.         *  @author  Stone.J 2011-4-9  
  17.        */   
  18.         public   static   class  Request  extends  Thread {  
  19.      
  20.             private   long  delay;  
  21.      
  22.             public  Request( long  delay){  
  23.                 this .delay  =  delay;  
  24.            }  
  25.      
  26.             public   void  run() {  
  27.                HttpClient hc  =   new  HttpClient();  
  28.                GetMethod req  =   new  GetMethod( " http://www.python.org/ftp/python/2.7.1/Python-2.7.1.tgz " );  
  29.                 try  {  
  30.                    TIMEOUT_QUEUE.offer( new  Timeout(delay  *   1000 , hc.getHttpConnectionManager()));  
  31.                    hc.executeMethod(req);  
  32.                }  catch  (Exception e) {  
  33.                    System.out.println(e);  
  34.                }  
  35.                req.releaseConnection();  
  36.            }  
  37.      
  38.        }  
  39.      
  40.         /**   
  41.         * 监工:监控线程,通过DelayQueue,阻塞得到最近超时的对象,强制关闭  
  42.         *   
  43.         *  @author  Stone.J 2011-4-9  
  44.          */   
  45.         public   static   class  Monitor  extends  Thread {  
  46.      
  47.            @Override 
  48.             public   void  run() {  
  49.                 while  ( true ) {  
  50.                     try  {  
  51.                        Timeout timeout  =  TIMEOUT_QUEUE.take();  
  52.                        timeout.forceClose();  
  53.                    }  catch  (InterruptedException e) {  
  54.                        System.out.println(e);  
  55.                    }  
  56.                }  
  57.            }  
  58.      
  59.        }  
  60.      
  61.         /**   
  62.         * 使用delay queue,对Delayed接口的实现 根据请求当前时间+该请求允许timeout时间,和当前时间比较,判断是否已经超时  
  63.         *   
  64.         *  @author  Stone.J 2011-4-9  
  65.          */   
  66.         public   static   class  Timeout  implements  Delayed {  
  67.      
  68.             private   long                   debut;  
  69.             private   long                   delay;  
  70.             private  HttpConnectionManager manager;  
  71.      
  72.             public  Timeout( long  delay, HttpConnectionManager manager){  
  73.                 this .debut  =  System.currentTimeMillis();  
  74.                 this .delay  =  delay;  
  75.                 this .manager  =  manager;  
  76.           }  
  77.      
  78.             public   void  forceClose() {  
  79.                System.out.println( this .debut  +   " : "   +   this .delay);  
  80.                 if  (manager  instanceof  SimpleHttpConnectionManager) {  
  81.                    ((SimpleHttpConnectionManager) manager).shutdown();  
  82.                }  
  83.                 if  (manager  instanceof  MultiThreadedHttpConnectionManager) {  
  84.                    ((MultiThreadedHttpConnectionManager) manager).shutdown();  
  85.                }  
  86.            }  
  87.      
  88.            @Override 
  89.             public   int  compareTo(Delayed o) {  
  90.                 if  (o  instanceof  Timeout) {  
  91.                    Timeout timeout  =  (Timeout) o;  
  92.                     if  ( this .debut  +   this .delay  ==  timeout.debut  +  timeout.delay) {  
  93.                         return   0 ;  
  94.                    }  else   if  ( this .debut  +   this .delay  >  timeout.debut  +  timeout.delay) {  
  95.                         return   1 ;  
  96.                    }  else  {  
  97.                         return   - 1 ;  
  98.                    }  
  99.                }  
  100.                return   0 ;  
  101.           }  
  102.     
  103.           @Override 
  104.            public   long  getDelay(TimeUnit unit) {  
  105.                return  debut  +  delay  -  System.currentTimeMillis();  
  106.           }  
  107.     
  108.       }  
  109.     
  110.   }  

【编辑推荐】

  1. Hibernate批量更新与删除实例浅析
  2. 简述Hibernate Synchronizer学习笔记
  3. Hibernate column属性简介
  4. 概括Hibernate查询语言
  5. Hibernate cartridge学习总结

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...