您好,登錄后才能下訂單哦!
這篇文章主要介紹HttpClient使用過程中的安全隱患有哪些,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
HttpClient使用過程中的安全隱患,這個(gè)有些標(biāo)題黨。因?yàn)檫@本身不是HttpClient的問題,而是使用者的問題。
安全隱患場(chǎng)景說明:
一旦請(qǐng)求大數(shù)據(jù)資源,則HttpClient線程會(huì)被長(zhǎng)時(shí)間占有。即便調(diào)用了org.apache.commons.httpclient.HttpMethod#releaseConnection()方法,也無濟(jì)于事。
如果請(qǐng)求的資源是應(yīng)用可控的,那么不存在任何問題??墒乔∏∥覀儜?yīng)用的使用場(chǎng)景是,請(qǐng)求資源由用戶自行輸入,于是乎,我們不得不重視這個(gè)問題。
我們跟蹤releaseConnection代碼發(fā)現(xiàn):
org.apache.commons.httpclient.HttpMethodBase#releaseConnection()
public void releaseConnection() { try { if ( this .responseStream != null ) { try { // FYI - this may indirectly invoke responseBodyConsumed. this .responseStream.close(); } catch (IOException ignore) { } } } finally { ensureConnectionRelease(); } }
org.apache.commons.httpclient.ChunkedInputStream#close()
public void close() throws IOException { if ( ! closed) { try { if ( ! eof) { exhaustInputStream( this ); } } finally { eof = true ; closed = true ; } } }
org.apache.commons.httpclient.ChunkedInputStream#exhaustInputStream(InputStream inStream)
static void exhaustInputStream(InputStream inStream) throws IOException { // read and discard the remainder of the message byte buffer[] = new byte [ 1024 ]; while (inStream.read(buffer) >= 0 ) { ; } }
看到了吧,所謂的丟棄response,其實(shí)是讀完了一次請(qǐng)求的response,只是不做任何處理罷了。
想想也是,HttpClient的設(shè)計(jì)理念是重復(fù)使用HttpConnection,豈能輕易被強(qiáng)制close呢。
怎么辦?有朋友說,不是有time out設(shè)置嘛,設(shè)置下就可以下。
我先來解釋下Httpclient中兩個(gè)time out的概念:
1.public static final String CONNECTION_TIMEOUT = "http.connection.timeout";
即創(chuàng)建socket連接的超時(shí)時(shí)間: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
而在我上面場(chǎng)景中,這兩個(gè)timeout都不滿足,確實(shí)是由于資源過大,而占用了大量的請(qǐng)求時(shí)間。
問題總是要解決的,解決思路如下:
1.利用DelayQueue,管理所有請(qǐng)求
2.利用一個(gè)異步線程監(jiān)控,關(guān)閉超長(zhǎng)時(shí)間的請(qǐng)求
演示代碼如下:
public class Misc2 { private static final DelayQueue < Timeout > TIMEOUT_QUEUE = new DelayQueue < Timeout > (); public static void main(String[] args) throws Exception { new Monitor().start(); // 超時(shí)監(jiān)控線程 new Request( 4 ).start(); // 模擬***個(gè)下載 new Request( 3 ).start(); // 模擬第二個(gè)下載 new Request( 2 ).start(); // 模擬第三個(gè)下載 } /** * 模擬一次HttpClient請(qǐng)求 * * @author Stone.J 2011-4-9 */ public static class Request extends Thread { private long delay; public Request( long delay){ this .delay = delay; } public void run() { HttpClient hc = new HttpClient(); GetMethod req = new GetMethod( " http://www.python.org/ftp/python/2.7.1/Python-2.7.1.tgz " ); try { TIMEOUT_QUEUE.offer( new Timeout(delay * 1000 , hc.getHttpConnectionManager())); hc.executeMethod(req); } catch (Exception e) { System.out.println(e); } req.releaseConnection(); } } /** * 監(jiān)工:監(jiān)控線程,通過DelayQueue,阻塞得到最近超時(shí)的對(duì)象,強(qiáng)制關(guān)閉 * * @author Stone.J 2011-4-9 */ public static class Monitor extends Thread { @Override public void run() { while ( true ) { try { Timeout timeout = TIMEOUT_QUEUE.take(); timeout.forceClose(); } catch (InterruptedException e) { System.out.println(e); } } } } /** * 使用delay queue,對(duì)Delayed接口的實(shí)現(xiàn) 根據(jù)請(qǐng)求當(dāng)前時(shí)間+該請(qǐng)求允許timeout時(shí)間,和當(dāng)前時(shí)間比較,判斷是否已經(jīng)超時(shí) * * @author Stone.J 2011-4-9 */ public static class Timeout implements Delayed { private long debut; private long delay; private HttpConnectionManager manager; public Timeout( long delay, HttpConnectionManager manager){ this .debut = System.currentTimeMillis(); this .delay = delay; this .manager = manager; } public void forceClose() { System.out.println( this .debut + " : " + this .delay); if (manager instanceof SimpleHttpConnectionManager) { ((SimpleHttpConnectionManager) manager).shutdown(); } if (manager instanceof MultiThreadedHttpConnectionManager) { ((MultiThreadedHttpConnectionManager) manager).shutdown(); } } @Override public int compareTo(Delayed o) { if (o instanceof Timeout) { Timeout timeout = (Timeout) o; if ( this .debut + this .delay == timeout.debut + timeout.delay) { return 0 ; } else if ( this .debut + this .delay > timeout.debut + timeout.delay) { return 1 ; } else { return - 1 ; } } return 0 ; } @Override public long getDelay(TimeUnit unit) { return debut + delay - System.currentTimeMillis(); } } }
以上是“HttpClient使用過程中的安全隱患有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。