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,但是发现同事已经有比较纤细的描述,就加个链接吧 (人懒,没办法)
分享到:
相关推荐
在IT行业中,HttpClient是一个常用的Java库,用于执行HTTP和HTTPS请求。这个实例主要涉及如何配置HttpClient来忽略SSL(Secure Socket Layer)...但请记住,忽视SSL验证在生产环境中可能会导致安全隐患,务必谨慎对待。
书中的这部分可能会讲述如何在C#中使用HttpClient类进行安全的HTTP通信,以及如何处理SSL/TLS证书验证。 五、异常处理与错误安全 异常处理是保障程序稳定性的关键,书中会讲解如何使用try-catch-finally语句块进行...
5. **网络安全**:在网络编程中,如使用Socket或HttpClient,必须确保通信过程的安全,例如使用SSL/TLS进行安全传输,防止中间人攻击。 6. **线程安全**:多线程环境下,共享资源的并发访问可能导致数据不一致或...
支持GET和POST方法,特别的是,它还能无视HTTPS证书,这对于开发、测试阶段非常有用,但请注意在生产环境中应谨慎使用,因为忽视证书验证可能带来安全隐患。 1. **HTTP GET 请求** HTTP GET请求是最基础的请求方式...
6. **安全性考虑**:SSO虽然方便,但也有安全隐患,如中间人攻击和票证重放攻击。因此,确保HTTPS(加密的HTTP)用于所有通信,以及实施严格的票证生命周期管理是至关重要的。 7. **测试有效性**:提供者声明代码已...
自动登录虽方便,但也存在安全隐患。用户应确保程序在本地安全运行,避免泄露用户名和密码。此外,可以使用加密技术对存储的用户名和密码进行加密,减少信息被窃取的风险。 五、扩展功能: 1. 存储和读取配置:使用...
2. **设置信任所有证书**:由于开发环境可能使用自签名证书,需要关闭SSL验证,但这在生产环境中应避免,因为会带来安全隐患。 3. **建立连接**:创建`URL`对象,打开与顺丰接口的连接,并将其转换为`...
请注意,这种做法仅适用于开发和测试环境,因为全信任何证书可能会导致安全隐患。在生产环境中,应该使用标准的信任管理器并处理证书验证。 总结一下,通过Java的JSSE,我们可以直接使用Socket建立HTTPS连接,步骤...
通常,这不建议在生产环境中使用,因为它可能导致安全隐患。在Flutter中,这可能通过dart:io库的HttpClient类进行实现,通过设置onBadCertificate回调来禁用SSL验证。 `Doldrums`:Doldrums可能是一个专门为Flutter...
6. **安全考虑**:动态加载网络上的类可能会带来安全隐患,因此在实际应用中,需要对加载的类进行签名验证或者限制可加载的网络地址,以确保安全性。 在给定的`ClassloaderTest`文件中,可能包含了一个示例代码,...
6. **安全考虑**:尽管XML文件方便了数据存储,但明文存储密码存在安全隐患。为了保护用户信息安全,开发者应使用加密算法对密码进行处理,如使用SHA256等哈希函数,或者更高级的加密机制如AES,确保即使数据被盗,...
需要注意的是,这种方法虽然解决了在WinForm应用中验证Moss的身份认证问题,但它存在一些潜在的安全隐患。首先,明文传递用户名和密码并不安全,尤其是在代码中硬编码。其次,使用COM组件可能会引入版本兼容性问题。...