2009-09-24 246 views
0

我尝试模仿由封闭的源应用程序发送的网络请求。下面 是从关闭源应用程序所捕获的网络请求快照:使用Jakarta HttpClient来模拟POST网络请求

- Http: Request, POST /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage 
    Command: POST 
    - URI: /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage? 
    Location: /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage 
    ProtocolVersion: HTTP/1.1 
    - ContentType: application/x-www-form-urlencoded 
    MediaType: application/x-www-form-urlencoded 
    Cache-Control: no-cache 
    Pragma: no-cache 
    UserAgent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_06 
    Host: www.xxx.com:20000 
    Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 
    Connection: keep-alive 
    ContentLength: 164 
    HeaderEnd: CRLF 
    - payload: HttpContentType = application/x-www-form-urlencoded 
    [SORT]: 0,1,0,10,5,0,KL,0 
    [FIELD]: 33,38,51,58,68,88,78,98,99,101,56,57,69,70,71,72,89,90,91,92,59,60,61,62,79,80,81,82 
    [LIST]: 1155.KL,1295.KL,7191.KL,0097.KL,2267.KL 

我使用的HttpClient模仿上述请求。

/** 
* @param args the command line arguments 
*/ 
public static void main(String[] args) { 
    try { 
     // TODO code application logic here 
     HttpClient httpClient = new HttpClient(); 
     httpClient.getParams().setParameter(HttpMethodParams.USER_AGENT, "Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_06"); 

     PostMethod post = new PostMethod("http://www.xxx.com:20000/%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage?"); 

     NameValuePair[] data = { 
      new NameValuePair("SORT", "0,1,0,10,5,0,KL,0"), 
      new NameValuePair("FIELD", "33,38,51,58,68,88,78,98,99,101,56,57,69,70,71,72,89,90,91,92,59,60,61,62,79,80,81,82"), 
      new NameValuePair("LIST", "1155.KL,1295.KL,7191.KL,0097.KL,2267.KL") 
     }; 
     post.setRequestBody(data); 
     httpClient.executeMethod(post); 
     System.out.println(post.getResponseBodyAsString());  
    } 
    catch (Exception exp) { 
     exp.printStackTrace(); 
    } 
} 

但是,服务器端没有回应。我试图捕捉我自己的网络请求快照:

- Http: Request, POST /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage 
    Command: POST 
    - URI: /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage 
    Location: /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage 
    ProtocolVersion: HTTP/1.1 
    UserAgent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_06 
    Host: www.xxx.com:20000 
    ContentLength: 234 
    - ContentType: application/x-www-form-urlencoded 
    MediaType: application/x-www-form-urlencoded 
    HeaderEnd: CRLF 
    - payload: HttpContentType = application/x-www-form-urlencoded 
    SORT: 0%2C1%2C0%2C10%2C5%2C0%2CKL%2C0 
    FIELD: 33%2C38%2C51%2C58%2C68%2C88%2C78%2C98%2C99%2C101%2C56%2C57%2C69%2C70%2C71%2C72%2C89%2C90%2C91%2C92%2C59%2C60%2C61%2C62%2C79%2C80%2C81%2C82 
    LIST: 1155.KL%2C1295.KL%2C7191.KL%2C0097.KL%2C2267.KL 

看来,有两个主要不同:

(1)URI

(2)有效载荷

请问有什么错过了我的httpclient代码?

经过多次实验,我意识到,httpclient在我的有效载荷上执行URL编码。它明确地转向

1155.KL,1295.KL,7191.KL,0097.KL,2267.KL

1155.KL%2C1295.KL%2C7191.KL%2C0097.KL %2C2267.KL

为了避免这种情况,我编写了一个测试代码。以下测试代码有效!

try { 
    Socket socket = new Socket("www.xxx.com", 20000); 
    PrintWriter out = new PrintWriter(socket.getOutputStream(), true); 
    final String body = "[SORT]=0,1,0,10,5,0,KL,0&[FIELD]=33,38,51,58,68,88,78,98,99,101,56,57,69,70,71,72,89,90,91,92,59,60,61,62,79,80,81,82&[LIST]=1155.KL,1295.KL,7191.KL,0097.KL,2267.KL"; 
    final int length = body.length(); 
    final String s = "POST /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage? HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nUser-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_06\r\nHost: www.xxx.com:20000\r\nAccept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\nConnection: keep-alive\r\nContent-Length: "+length+"\r\n\r\n" + body; 
    out.println(s); 

    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    while(true) { 
      String ss = in.readLine(); 
      if (ss == null) break; 
      System.out.println(ss); 
    } 

} 
catch (Exception exp) { 
} 

以下是拍摄快照:

Frame: Number = 16, Captured Frame Length = 597, MediaType = ETHERNET 
+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[7C-04-20-00-01-00],SourceAddress:[01-00-01-00-00-00] 
+ Ipv4: Src = 10.176.181.55, Dest = 202.75.55.23, Next Protocol = TCP, Packet ID = 956, Total IP Length = 583 
+ Tcp: Flags=...AP..., SrcPort=49253, DstPort=20000, PayloadLen=543, Seq=3920474750 - 3920475293, Ack=3537289604, Win=4380 (scale factor 0x2) = 17520 
- Http: Request, POST /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage 
    Command: POST 
    + URI: /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage? 
    ProtocolVersion: HTTP/1.1 
    + ContentType: application/x-www-form-urlencoded 
    Cache-Control: no-cache 
    Pragma: no-cache 
    UserAgent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_06 
    Host: n2ntbfd03.asiaebroker.com:20000 
    Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 
    Connection: keep-alive 
    ContentLength: 164 
    HeaderEnd: CRLF 
    - payload: HttpContentType = application/x-www-form-urlencoded 
    [SORT]: 0,1,0,10,5,0,KL,0 
    [FIELD]: 33,38,51,58,68,88,78,98,99,101,56,57,69,70,71,72,89,90,91,92,59,60,61,62,79,80,81,82 
    [LIST]: 1155.KL,1295.KL,7191.KL,0097.KL,2267.KL 
+0

可以捕捉到原始的请求?也许在你的快照中出现的列表是这样发布的:SORT = 0&SORT = 1&SORT = 0 ...但是你用来捕获请求的软件正在做一些漂亮的列表打印。 – Serxipc 2009-09-24 08:09:45

+0

现在真正的问题是,我如何避免HttpClient在我的负载上执行URL编码? – 2009-09-24 13:02:52

+0

请尝试http://www.fiddler2.com/或http://www.charlesproxy.com/来捕获原始请求,以便我们看到如何发布这些列表。 提琴手是免费的,但只适用于Windows。 Charles有30天的免费试用期。 – Serxipc 2009-09-24 13:56:55

回答

1

由参数名称显示在您的捕获SORT VS [分页]的方式来看。我怀疑服务器期待您发送带有多个表单控件数组,像

SORT = 0 & SORT = 1个& SORT = 0 ...

他们可能做到这一点作为一种安全措施,因为这样可以不会用HTML来完成。

编辑:您需要将您的参数,这样,

NameValuePair[] data = { 
     new NameValuePair("SORT", "0"), 
     new NameValuePair("SORT", "1"), 
     ... 
     new NameValuePair("FIELD", "33"), 
     ... 
    }; 
+0

这是选择多个值的发布方式。 – Serxipc 2009-09-24 13:46:49

+0

看我的编辑.................... – 2009-09-24 14:05:33

+0

不,这不起作用。服务器期待看到原始的“[SORT] = 0,1,0,10,5,0,KL,0和[FIELD] = 33,...”。但HttpClient将始终执行URL编码。我测试使用原始TCP套接字与数据withouth编码,它工作得很好。但是,我需要使用HttpClient,因为它支持NTLM。 – 2009-09-24 17:20:23

0

你是如何创建快照?参数名称的括号是什么意思?对于相同的参数,是否有多个值而不是逗号分隔的值,或者参数名称是否应放在括号中?

1

您还缺少标题: 接受 的Cache-Control 附注

的单独接受头可能是足够的服务器与一些有意义的回应。尝试这样的事情对于HttpClient的4:

httpclient.addRequestInterceptor(new HttpRequestInterceptor() { 
     public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { 
     request.setHeader("Pragma","no-cache"); 
     request.setHeader("Cache-Control","no-cache"); 
     request.setHeader("Accept","text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"); 
     } 
    }); 

或者这样东西的HttpClient 3.x的:

method.setRequestHeader("Pragma","no-cache"); 
method.setRequestHeader("Cache-Control","no-cache"); 
method.setRequestHeader("Accept","text/html, image/gif, image/jpeg, *; q=.2, */*; 
+0

对不起。我正在使用HttpClient 3.1 – 2009-09-24 07:33:39