记录 Java 应用程序的所有网络交互

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18512522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:41:44  来源:igfitidea点击:

Log all network interactions of Java application

javadebuggingrpc

提问by Hnatt

I have a monstrous Java app (a client of little-known application server GNUEnterprise) and its source, which I can compile back after making some changes to it. The app uses network heavily and I need to monitor each request and response. I could use a sniffer like Wireshark, but the application works with its server over SSL, so not knowing SSL-certificate's private key any sniffed traffic is pretty useless.

我有一个可怕的 Java 应用程序(鲜为人知的应用程序服务器 GNUEnterprise 的客户端)及其源代码,我可以在对其进行一些更改后重新编译。该应用程序大量使用网络,我需要监视每个请求和响应。我可以使用像 Wireshark 这样的嗅探器,但是该应用程序通过 SSL 与其服务器一起工作,因此不知道 SSL 证书的私钥,任何嗅探到的流量都非常无用。

What can I do to make every request and response to be logged from the application itself? I need to see all sent and received headers. I don't want to alter all code responsible for network interaction. What I want is to put a code like

我该怎么做才能从应用程序本身记录每个请求和响应?我需要查看所有发送和接收的标头。我不想更改所有负责网络交互的代码。我想要的是放一个代码

Network.setDefaultLogger(myCustomLoggerInstance);

somewhere near start of the app and then in the myCustomLoggerInstancedo all the logging I need.

在应用程序开始附近的某个地方,然后在myCustomLoggerInstance做我需要的所有日志记录。

Also, given all network operations are made with URLConnections, I can get response headers with con.getHeaderFields()and request headers with con.getRequestProperties(). But why cookies aren't there? How to dump sent and received cookies in the same way?

此外,鉴于所有网络操作都是使用URLConnections 进行的,我可以con.getHeaderFields()使用con.getRequestProperties(). 但是为什么没有cookies呢?如何以相同的方式转储发送和接收的 cookie?

EDIT: What I'm trying to reach is to mimic RPC-application's communication with it's server over SSL, say, using curl. For this I need to get detailed log of app's network traffic.

编辑:我想要达到的是通过 SSL 模拟 RPC 应用程序与其服务器的通信,例如,使用curl. 为此,我需要获取应用程序网络流量的详细日志。

采纳答案by GreyFairer

Can't you use a logging proxy server, e.g. http://www.charlesproxy.com/or http://fiddler2.com/? Charles Proxy can also decode AMF requests, Fiddler is the champion for SSL interception.

您不能使用日志代理服务器,例如http://www.charlesproxy.com/http://fiddler2.com/吗?Charles Proxy 也可以解码 AMF 请求,Fiddler 是 SSL 拦截的冠军。

IIRC you can set system properties http.proxyHost and http.proxyPort to 127.0.0.1 and 8888, and java URLConnections will automatically connect via your logging proxy server, and you get a nice view of your HTTP Traffic.

IIRC 您可以将系统属性 http.proxyHost 和 http.proxyPort 设置为 127.0.0.1 和 8888,并且 java URLConnections 将通过您的日志代理服务器自动连接,您可以很好地查看 HTTP 流量。

Or, if the intention is to be able to replay the communication, use JMeter HTTP Proxy, this records in a format that is suitable for replay. It has also built-in support for handling cookies.

或者,如果目的是能够重放通信,请使用 JMeter HTTP 代理,以适合重放的格式记录。它还内置了处理 cookie 的支持。

If the application uses nice web services, SoapUI also has a monitoring proxy that intercepts web service calls for which you have imported the WSDL.

如果应用程序使用了不错的 Web 服务,SoapUI 也有一个监视代理来拦截您导入 WSDL 的 Web 服务调用。

回答by giampaolo

I just want to post a snippet of code that you can use at starting point. I do not have a"global" logger but with small changes to existing code you can reach your goal. I "log" on standard output, since your problem can be split into two pieces: getting the info from UrlConnection and store it for further reference.

我只想发布您可以在起点使用的代码片段。我没有“全局”记录器,但是对现有代码进行一些小的更改就可以实现您的目标。我在标准输出上“登录”,因为您的问题可以分为两部分:从 UrlConnection 获取信息并将其存储以供进一步参考。

This code logs the request:

此代码记录请求:

public class URLConnectionReader {

  public static void main(String[] args) throws Exception {
  URL oracle = new URL("http://www.google.com/");
  URLConnection yc = oracle.openConnection();

  String headerName = null;
  for (int i = 1; (headerName = yc.getHeaderFieldKey(i)) != null; i++) {
    if (headerName.equals("Set-Cookie")) {
      String cookie = yc.getHeaderField(i);
      System.out.println("Cookie  ::  " + cookie);
    } else {
      System.out.println("Header: "+ yc.getHeaderField(i));
    }
  }

  BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
  String inputLine;
  while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);
  in.close();
}

}

}

saving all this data to one or more files is not hard. If you believe that I'm on right way for you problem, I would be glad to edit the answer with other details as needed.

将所有这些数据保存到一个或多个文件并不难。如果您认为我对您的问题是正确的,我很乐意根据需要使用其他详细信息编辑答案。

回答by GreyFairer

I dug a little further, and apparently, HttpURLConnection comes with java.util.logging enabled by default.

我进一步挖掘了一点,显然 HttpURLConnection 默认启用了 java.util.logging。

See related questions: Java: Display request of an HttpURLConnection before sendingand How to enable wire logging for a java HttpURLConnection traffic?

请参阅相关问题: Java:在发送之前显示 HttpURLConnection 的请求以及如何为 java HttpURLConnection 流量启用线路日志记录?

Java.util.logging was Sun's (failed) attempt at standardizing logging providers in Java 1.4. You can bridge it to SLF4J via the jul-to-slf4j module if you want to avoid tweaking system properties.

Java.util.logging 是 Sun 在 Java 1.4 中标准化日志记录提供程序的(失败)尝试。如果您想避免调整系统属性,您可以通过 jul-to-slf4j 模块将其桥接到 SLF4J。

But I would still prefer Fiddler or JMeter proxy though :-)

但我仍然更喜欢 Fiddler 或 JMeter 代理:-)

回答by Ehsan Khodarahmi

If you want to log network traffic & you have URLConnection objects then the problem is already solved!
If you want to log at stream level, you need to write a little wrapper on top of your I/O streams & log all data before transfer them to lower network layers, otherwise you can use connection objects directly to get required info & log them.
For managing cookies, you should use java.net.HttpCookiewhich is introduced in java 6. Only thing you have to do is to create an instance of CookieManager & set it as default cookie manager:

如果你想记录网络流量并且你有 URLConnection 对象,那么问题已经解决了!
如果要在流级别进行日志记录,则需要在 I/O 流之上编写一个小包装器并记录所有数据,然后再将它们传输到较低的网络层,否则您可以直接使用连接对象来获取所需信息并记录它们.
要管理 cookie,您应该使用java.net.HttpCookiejava 6 中引入的 which。您唯一要做的就是创建一个 CookieManager 实例并将其设置为默认 cookie 管理器:

CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

& you can use it for managing connection cookies!

& 您可以使用它来管理连接 cookie!

回答by Julius Musseau

A quick way to log all SSL traffic is to startup java with:

记录所有 SSL 流量的一种快速方法是使用以下命令启动 java:

-Djavax.net.debug=all

Or set it as a system property:

或将其设置为系统属性:

System.setProperty("javax.net.debug","all");

Brace yourself. Standard out gets NOISY if you do this!

振作起来。如果你这样做,标准输出会变得嘈杂!

(*Note: only logs SSL traffic and SSL debug info (handshakes, etc). Regular sockets are not logged.)

(*注意:仅记录 SSL 流量和 SSL 调试信息(握手等)。不记录常规套接字。)