<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    stone2083

    HttpClient使用過程中的安全隱患

    HttpClient使用過程中的安全隱患,這個有些標(biāo)題黨。因為這本身不是HttpClient的問題,而是使用者的問題。

    安全隱患場景說明:
    一旦請求大數(shù)據(jù)資源,則HttpClient線程會被長時間占有。即便調(diào)用了org.apache.commons.httpclient.HttpMethod#releaseConnection()方法,也無濟于事。
    如果請求的資源是應(yīng)用可控的,那么不存在任何問題。可是恰恰我們應(yīng)用的使用場景是,請求資源由用戶自行輸入,于是乎,我們不得不重視這個問題。

    我們跟蹤releaseConnection代碼發(fā)現(xiàn):
    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的設(shè)計理念是重復(fù)使用HttpConnection,豈能輕易被強制close呢。

    怎么辦?有朋友說,不是有time out設(shè)置嘛,設(shè)置下就可以下。
    我先來解釋下Httpclient中兩個time out的概念:
    1.public static final String CONNECTION_TIMEOUT = "http.connection.timeout";
    即創(chuàng)建socket連接的超時時間:java.net.Socket#connect(SocketAddress endpoint, int timeout)中的timeout

    2.public static final String SO_TIMEOUT = "http.socket.timeout";
    即read data過程中,等待數(shù)據(jù)的timeout:java.net.Socket#setSoTimeout(int timeout)中的timeout

    而在我上面場景中,這兩個timeout都不滿足,確實是由于資源過大,而占用了大量的請求時間。

    問題總是要解決的,解決思路如下:
    1.利用DelayQueue,管理所有請求
    2.利用一個異步線程監(jiān)控,關(guān)閉超長時間的請求

    演示代碼如下:
      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(); // 超時監(jiān)控線程
      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      * 監(jiān)工:監(jiān)控線程,通過DelayQueue,阻塞得到最近超時的對象,強制關(guān)閉
     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接口的實現(xiàn) 根據(jù)請求當(dāng)前時間+該請求允許timeout時間,和當(dāng)前時間比較,判斷是否已經(jīng)超時
     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,但是發(fā)現(xiàn)同事已經(jīng)有比較纖細的描述,就加個鏈接吧 (人懶,沒辦法)
    http://agapple.iteye.com/blog/916837
    http://agapple.iteye.com/blog/947133

    備注:
    HttpClient3.1中,SimpleHttpConnectionManager才有shutdown方法,3.0.1中還存在 :)

    posted on 2011-04-09 20:46 stone2083 閱讀(4762) 評論(0)  編輯  收藏 所屬分類: java

    主站蜘蛛池模板: 成年女人A毛片免费视频| 无限动漫网在线观看免费| 久久国产亚洲精品无码| 美女视频黄免费亚洲| 边摸边脱吃奶边高潮视频免费| 亚洲午夜福利在线观看| 2015日韩永久免费视频播放| 亚洲成AV人片高潮喷水| 久久精品国产亚洲AV果冻传媒| 欧洲乱码伦视频免费| 一本到卡二卡三卡免费高| 亚洲理论在线观看| 亚洲福利在线播放| 在免费jizzjizz在线播| 天堂亚洲免费视频| 亚洲乱码日产精品BD在线观看| 亚洲国产精品尤物yw在线| 1000部拍拍拍18勿入免费视频下载 | 亚洲乱码中文字幕小综合| 日韩高清免费观看| 久久久久久久99精品免费观看| 亚洲国产夜色在线观看| 国产成人精品亚洲精品| 91成年人免费视频| 中国一级特黄的片子免费 | 日韩亚洲欧洲在线com91tv| a级毛片无码免费真人| 青柠影视在线观看免费| 亚洲国产精品精华液| 久久亚洲精品成人AV| 国产日产亚洲系列最新| 天天天欲色欲色WWW免费| 一区二区三区观看免费中文视频在线播放 | 7723日本高清完整版免费| 皇色在线免费视频| 亚洲av色香蕉一区二区三区蜜桃| 亚洲欧洲在线观看| 国产亚洲精品AA片在线观看不加载| 在线永久免费观看黄网站| 亚洲w码欧洲s码免费| 好爽又高潮了毛片免费下载|