当前位置:编程学习 > 网站相关 >>

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="Stone.Jmailto: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="Stone.Jmailto: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      

补充:综合编程 , 安全编程 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,