`
buliedian
  • 浏览: 1237782 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

HttpClient使用过程中的安全隐患

阅读更多

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  <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> 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  <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> 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  <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> 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  }



本来还想详细讲下DelayQueue,但是发现同事已经有比较纤细的描述,就加个链接吧 (人懒,没办法)

2
3
分享到:
评论
3 楼 kimmking 2011-04-13  
C_J 写道
引用

连接里的长时间数据处理,导致不能释放,其他后续请求排队直到处理或超时。


这是一种什么情景,能详细说明下吗?



你把两个超时设大,max和perhost连接数设成1,100个并发请求一个服务端sleep也很长的地址。

就知道了。


跟数据库连接池一样的。
2 楼 C_J 2011-04-13  
引用

连接里的长时间数据处理,导致不能释放,其他后续请求排队直到处理或超时。


这是一种什么情景,能详细说明下吗?


1 楼 kimmking 2011-04-13  
httpclient的思想是重用connection,合理控制资源池大小。
所以,连接里的长时间数据处理,导致不能释放,其他后续请求排队直到处理或超时。
这个跟线程池一个道理。

shutdown太暴力了,MultiThreadedHttpConnectionManager下太重了,alive的都close了。

觉得觉得如果能在处理前,根据responseheader的content-length或者multipart时的post时的filesize,知道这个处理不完,直接不加入到httpclient的处理逻辑里来的方便。

按你的方法,MultiThreadedHttpConnectionManager也可以轻量点,拿到当前的connection,close掉,然后从manager里去掉。

相关推荐

    httpClient实例httpClient调用 http/https实例 忽略SSL验证

    在IT行业中,HttpClient是一个常用的Java库,用于执行HTTP和HTTPS请求。这个实例主要涉及如何配置HttpClient来忽略SSL(Secure Socket Layer)...但请记住,忽视SSL验证在生产环境中可能会导致安全隐患,务必谨慎对待。

    《C# 数据安全手册》清晰PDF电子版(十分经典)

    书中的这部分可能会讲述如何在C#中使用HttpClient类进行安全的HTTP通信,以及如何处理SSL/TLS证书验证。 五、异常处理与错误安全 异常处理是保障程序稳定性的关键,书中会讲解如何使用try-catch-finally语句块进行...

    Java安全学习项目.zip

    5. **网络安全**:在网络编程中,如使用Socket或HttpClient,必须确保通信过程的安全,例如使用SSL/TLS进行安全传输,防止中间人攻击。 6. **线程安全**:多线程环境下,共享资源的并发访问可能导致数据不一致或...

    c#Http请求封装类库.rar

    支持GET和POST方法,特别的是,它还能无视HTTPS证书,这对于开发、测试阶段非常有用,但请注意在生产环境中应谨慎使用,因为忽视证书验证可能带来安全隐患。 1. **HTTP GET 请求** HTTP GET请求是最基础的请求方式...

    单点登录CAS应用代码(HTTP)

    6. **安全性考虑**:SSO虽然方便,但也有安全隐患,如中间人攻击和票证重放攻击。因此,确保HTTPS(加密的HTTP)用于所有通信,以及实施严格的票证生命周期管理是至关重要的。 7. **测试有效性**:提供者声明代码已...

    C# 登录淘宝

    自动登录虽方便,但也存在安全隐患。用户应确保程序在本地安全运行,避免泄露用户名和密码。此外,可以使用加密技术对存储的用户名和密码进行加密,减少信息被窃取的风险。 五、扩展功能: 1. 存储和读取配置:使用...

    顺丰接口实例

    2. **设置信任所有证书**:由于开发环境可能使用自签名证书,需要关闭SSL验证,但这在生产环境中应避免,因为会带来安全隐患。 3. **建立连接**:创建`URL`对象,打开与顺丰接口的连接,并将其转换为`...

    直接通过Socket使用JSSE

    请注意,这种做法仅适用于开发和测试环境,因为全信任何证书可能会导致安全隐患。在生产环境中,应该使用标准的信任管理器并处理证书验证。 总结一下,通过Java的JSSE,我们可以直接使用Socket建立HTTPS连接,步骤...

    flutter逆向工具集

    通常,这不建议在生产环境中使用,因为它可能导致安全隐患。在Flutter中,这可能通过dart:io库的HttpClient类进行实现,通过设置onBadCertificate回调来禁用SSL验证。 `Doldrums`:Doldrums可能是一个专门为Flutter...

    网络类加载器实现

    6. **安全考虑**:动态加载网络上的类可能会带来安全隐患,因此在实际应用中,需要对加载的类进行签名验证或者限制可加载的网络地址,以确保安全性。 在给定的`ClassloaderTest`文件中,可能包含了一个示例代码,...

    QQ自动登录

    6. **安全考虑**:尽管XML文件方便了数据存储,但明文存储密码存在安全隐患。为了保护用户信息安全,开发者应使用加密算法对密码进行处理,如使用SHA256等哈希函数,或者更高级的加密机制如AES,确保即使数据被盗,...

    关于C#.net winform程序验证moss的集成身份认证实例

    需要注意的是,这种方法虽然解决了在WinForm应用中验证Moss的身份认证问题,但它存在一些潜在的安全隐患。首先,明文传递用户名和密码并不安全,尤其是在代码中硬编码。其次,使用COM组件可能会引入版本兼容性问题。...

Global site tag (gtag.js) - Google Analytics